Nodes: Allow adding multiple search items per node type in add menu #104794

Merged
Hans Goudey merged 3 commits from HooglyBoogly/blender:node-add-search-items into main 2023-02-20 19:17:14 +01:00
19 changed files with 160 additions and 24 deletions

View File

@ -98,6 +98,7 @@ class NodeMultiFunctionBuilder;
class GeoNodeExecParams;
class NodeDeclaration;
class NodeDeclarationBuilder;
class GatherAddNodeSearchParams;
class GatherLinkSearchOpParams;
} // namespace nodes
namespace realtime_compositor {
@ -122,6 +123,10 @@ using SocketGetGeometryNodesCPPValueFunction = void (*)(const struct bNodeSocket
using NodeGatherSocketLinkOperationsFunction =
void (*)(blender::nodes::GatherLinkSearchOpParams &params);
/* Adds node add menu operations that are specific to this node type. */
using NodeGatherAddOperationsFunction =
void (*)(blender::nodes::GatherAddNodeSearchParams &params);
using NodeGetCompositorOperationFunction = blender::realtime_compositor::NodeOperation
*(*)(blender::realtime_compositor::Context &context, blender::nodes::DNode node);
using NodeGetCompositorShaderNodeFunction =
@ -135,6 +140,7 @@ typedef void *NodeGeometryExecFunction;
typedef void *NodeDeclareFunction;
typedef void *NodeDeclareDynamicFunction;
typedef void *NodeGatherSocketLinkOperationsFunction;
typedef void *NodeGatherAddOperationsFunction;
typedef void *SocketGetCPPTypeFunction;
typedef void *SocketGetGeometryNodesCPPTypeFunction;
typedef void *SocketGetGeometryNodesCPPValueFunction;
@ -353,6 +359,13 @@ typedef struct bNodeType {
*/
NodeGatherSocketLinkOperationsFunction gather_link_search_ops;
/**
HooglyBoogly marked this conversation as resolved
Review

Add comment.

Add comment.
* Add to the list of search items gathered by the add-node search. The default behavior of
* adding a single item with the node name is usually enough, but node types can have any number
* of custom search items.
*/
NodeGatherAddOperationsFunction gather_add_node_search_ops;
/** True when the node cannot be muted. */
bool no_muting;

View File

@ -26,6 +26,8 @@
#include "WM_api.h"
#include "NOD_add_node_search.hh"
#include "ED_asset.h"
#include "ED_node.h"
@ -36,12 +38,9 @@ struct bContext;
namespace blender::ed::space_node {
struct AddNodeItem {
std::string ui_name;
nodes::AddNodeInfo info;
std::string identifier;
std::string description;
std::optional<AssetHandle> asset;
std::function<void(const bContext &, bNodeTree &, bNode &)> after_add_fn;
int weight = 0;
};
struct AddNodeSearchStorage {
@ -77,11 +76,11 @@ static void search_items_for_asset_metadata(const bNodeTree &node_tree,
}
AddNodeItem item{};
item.ui_name = ED_asset_handle_get_name(&asset);
item.info.ui_name = ED_asset_handle_get_name(&asset);
item.identifier = node_tree.typeinfo->group_idname;
item.description = asset_data.description == nullptr ? "" : asset_data.description;
item.info.description = asset_data.description == nullptr ? "" : asset_data.description;
item.asset = asset;
item.after_add_fn = [asset](const bContext &C, bNodeTree &node_tree, bNode &node) {
item.info.after_add_fn = [asset](const bContext &C, bNodeTree &node_tree, bNode &node) {
Main &bmain = *CTX_data_main(&C);
node.flag &= ~NODE_OPTIONS;
node.id = asset::get_local_id_from_asset_or_append_and_reuse(bmain, asset);
@ -139,9 +138,9 @@ static void gather_search_items_for_node_groups(const bContext &C,
continue;
}
AddNodeItem item{};
item.ui_name = node_group->id.name + 2;
item.info.ui_name = node_group->id.name + 2;
item.identifier = node_tree.typeinfo->group_idname;
item.after_add_fn = [node_group](const bContext &C, bNodeTree &node_tree, bNode &node) {
item.info.after_add_fn = [node_group](const bContext &C, bNodeTree &node_tree, bNode &node) {
Main &bmain = *CTX_data_main(&C);
node.id = &node_group->id;
id_us_plus(node.id);
@ -161,19 +160,18 @@ static void gather_add_node_operations(const bContext &C,
if (!(node_type->poll && node_type->poll(node_type, &node_tree, &disabled_hint))) {
continue;
}
if (StringRefNull(node_tree.typeinfo->group_idname) == node_type->idname) {
/* Skip the empty group type. */
if (!node_type->gather_add_node_search_ops) {
continue;
}
if (StringRefNull(node_type->ui_name).endswith("(Legacy)")) {
continue;
Vector<nodes::AddNodeInfo> info_items;
nodes::GatherAddNodeSearchParams params(*node_type, node_tree, info_items);
node_type->gather_add_node_search_ops(params);
for (nodes::AddNodeInfo &info : info_items) {
AddNodeItem item{};
item.info = std::move(info);
item.identifier = node_type->idname;
r_search_items.append(item);
}
AddNodeItem item{};
item.ui_name = IFACE_(node_type->ui_name);
item.identifier = node_type->idname;
item.description = TIP_(node_type->ui_description);
r_search_items.append(std::move(item));
}
NODE_TYPES_END;
@ -199,7 +197,7 @@ static void add_node_search_update_fn(
StringSearch *search = BLI_string_search_new();
for (AddNodeItem &item : storage.search_add_items) {
BLI_string_search_add(search, item.ui_name.c_str(), &item, item.weight);
BLI_string_search_add(search, item.info.ui_name.c_str(), &item, item.info.weight);
}
/* Don't filter when the menu is first opened, but still run the search
@ -210,7 +208,7 @@ static void add_node_search_update_fn(
for (const int i : IndexRange(filtered_amount)) {
AddNodeItem &item = *filtered_items[i];
if (!UI_search_item_add(items, item.ui_name.c_str(), &item, ICON_NONE, 0, 0)) {
if (!UI_search_item_add(items, item.info.ui_name.c_str(), &item, ICON_NONE, 0, 0)) {
break;
}
}
@ -234,8 +232,8 @@ static void add_node_search_exec_fn(bContext *C, void *arg1, void *arg2)
bNode *new_node = nodeAddNode(C, &node_tree, item->identifier.c_str());
BLI_assert(new_node != nullptr);
if (item->after_add_fn) {
item->after_add_fn(*C, node_tree, *new_node);
if (item->info.after_add_fn) {
item->info.after_add_fn(*C, node_tree, *new_node);
}
new_node->locx = storage.cursor.x / UI_DPI_FAC;
@ -266,7 +264,7 @@ static ARegion *add_node_search_tooltip_fn(
uiSearchItemTooltipData tooltip_data{};
BLI_strncpy(tooltip_data.description,
item->asset ? item->description.c_str() : TIP_(item->description.c_str()),
item->asset ? item->info.description.c_str() : TIP_(item->info.description.c_str()),
sizeof(tooltip_data.description));
return UI_tooltip_create_from_search_item_generic(C, region, item_rect, &tooltip_data);

View File

@ -39,6 +39,7 @@ set(INC
set(SRC
intern/add_node_search.cc
intern/derived_node_tree.cc
intern/geometry_nodes_lazy_function.cc
intern/geometry_nodes_log.cc
@ -54,6 +55,7 @@ set(SRC
intern/node_util.cc
intern/socket_search_link.cc
NOD_add_node_search.hh
NOD_common.h
NOD_composite.h
NOD_derived_node_tree.hh

View File

@ -0,0 +1,61 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include <functional>
#include "BLI_function_ref.hh"
#include "BLI_string_ref.hh"
#include "BLI_vector.hh"
#include "DNA_node_types.h" /* Necessary for eNodeSocketInOut. */
#include "NOD_node_declaration.hh"
struct bContext;
namespace blender::nodes {
struct AddNodeInfo {
using AfterAddFn = std::function<void(const bContext &C, bNodeTree &node_tree, bNode &node)>;
std::string ui_name;
std::string description;
AfterAddFn after_add_fn;
int weight = 0;
};
class GatherAddNodeSearchParams {
const bNodeType &node_type_;
const bNodeTree &node_tree_;
Vector<AddNodeInfo> &r_items;
public:
GatherAddNodeSearchParams(const bNodeType &node_type,
const bNodeTree &node_tree,
Vector<AddNodeInfo> &r_items)
: node_type_(node_type), node_tree_(node_tree), r_items(r_items)
{
}
const bNodeTree &node_tree() const
{
return node_tree_;
}
const bNodeType &node_type() const
{
return node_type_;
}
/**
* \param weight: Used to customize the order when multiple search items match.
*/
void add_item(std::string ui_name,
std::string description,
AddNodeInfo::AfterAddFn fn = {},
int weight = 0);
};
void search_node_add_ops_for_basic_node(GatherAddNodeSearchParams &params);
} // namespace blender::nodes

View File

@ -7,6 +7,7 @@
#include "BKE_node_runtime.hh"
#include "NOD_add_node_search.hh"
#include "NOD_socket_search_link.hh"
#include "node_composite_util.hh"
@ -35,4 +36,5 @@ void cmp_node_type_base(bNodeType *ntype, int type, const char *name, short ncla
ntype->updatefunc = cmp_node_update_default;
ntype->insert_link = node_insert_link_default;
ntype->gather_link_search_ops = blender::nodes::search_link_ops_for_basic_node;
ntype->gather_add_node_search_ops = blender::nodes::search_node_add_ops_for_basic_node;
}

View File

@ -428,6 +428,7 @@ void register_node_type_cmp_cryptomatte_legacy()
node_type_storage(
&ntype, "NodeCryptomatte", file_ns::node_free_cryptomatte, file_ns::node_copy_cryptomatte);
ntype.gather_link_search_ops = nullptr;
ntype.gather_add_node_search_ops = nullptr;
ntype.get_compositor_operation = legacy_file_ns::get_compositor_operation;
ntype.realtime_compositor_unsupported_message = N_(
"Node not supported in the Viewport compositor");

View File

@ -58,6 +58,7 @@ void register_node_type_cmp_sephsva()
&ntype, CMP_NODE_SEPHSVA_LEGACY, "Separate HSVA (Legacy)", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::cmp_node_sephsva_declare;
ntype.gather_link_search_ops = nullptr;
ntype.gather_add_node_search_ops = nullptr;
ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node;
nodeRegisterType(&ntype);
@ -112,6 +113,7 @@ void register_node_type_cmp_combhsva()
&ntype, CMP_NODE_COMBHSVA_LEGACY, "Combine HSVA (Legacy)", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::cmp_node_combhsva_declare;
ntype.gather_link_search_ops = nullptr;
ntype.gather_add_node_search_ops = nullptr;
ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node;
nodeRegisterType(&ntype);

View File

@ -58,6 +58,7 @@ void register_node_type_cmp_seprgba()
&ntype, CMP_NODE_SEPRGBA_LEGACY, "Separate RGBA (Legacy)", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::cmp_node_seprgba_declare;
ntype.gather_link_search_ops = nullptr;
ntype.gather_add_node_search_ops = nullptr;
ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node;
nodeRegisterType(&ntype);
@ -112,6 +113,7 @@ void register_node_type_cmp_combrgba()
&ntype, CMP_NODE_COMBRGBA_LEGACY, "Combine RGBA (Legacy)", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::cmp_node_combrgba_declare;
ntype.gather_link_search_ops = nullptr;
ntype.gather_add_node_search_ops = nullptr;
ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node;
nodeRegisterType(&ntype);

View File

@ -86,6 +86,7 @@ void register_node_type_cmp_sepycca()
ntype.declare = file_ns::cmp_node_sepycca_declare;
ntype.initfunc = file_ns::node_composit_init_mode_sepycca;
ntype.gather_link_search_ops = nullptr;
ntype.gather_add_node_search_ops = nullptr;
ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node;
nodeRegisterType(&ntype);
@ -174,6 +175,7 @@ void register_node_type_cmp_combycca()
ntype.declare = file_ns::cmp_node_combycca_declare;
ntype.initfunc = file_ns::node_composit_init_mode_combycca;
ntype.gather_link_search_ops = nullptr;
ntype.gather_add_node_search_ops = nullptr;
ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node;
nodeRegisterType(&ntype);

View File

@ -58,6 +58,7 @@ void register_node_type_cmp_sepyuva()
&ntype, CMP_NODE_SEPYUVA_LEGACY, "Separate YUVA (Legacy)", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::cmp_node_sepyuva_declare;
ntype.gather_link_search_ops = nullptr;
ntype.gather_add_node_search_ops = nullptr;
ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node;
nodeRegisterType(&ntype);
@ -112,6 +113,7 @@ void register_node_type_cmp_combyuva()
&ntype, CMP_NODE_COMBYUVA_LEGACY, "Combine YUVA (Legacy)", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::cmp_node_combyuva_declare;
ntype.gather_link_search_ops = nullptr;
ntype.gather_add_node_search_ops = nullptr;
ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node;
nodeRegisterType(&ntype);

View File

@ -3,6 +3,7 @@
#include "node_function_util.hh"
#include "node_util.h"
#include "NOD_add_node_search.hh"
#include "NOD_socket_search_link.hh"
static bool fn_node_poll_default(const bNodeType * /*ntype*/,
@ -23,4 +24,5 @@ void fn_node_type_base(bNodeType *ntype, int type, const char *name, short nclas
ntype->poll = fn_node_poll_default;
ntype->insert_link = node_insert_link_default;
ntype->gather_link_search_ops = blender::nodes::search_link_ops_for_basic_node;
ntype->gather_add_node_search_ops = blender::nodes::search_node_add_ops_for_basic_node;
}

View File

@ -10,6 +10,7 @@
#include "BKE_mesh_runtime.h"
#include "BKE_pointcloud.h"
#include "NOD_add_node_search.hh"
#include "NOD_socket_search_link.hh"
namespace blender::nodes {
@ -58,4 +59,5 @@ void geo_node_type_base(bNodeType *ntype, int type, const char *name, short ncla
ntype->poll = geo_node_poll_default;
ntype->insert_link = node_insert_link_default;
ntype->gather_link_search_ops = blender::nodes::search_link_ops_for_basic_node;
ntype->gather_add_node_search_ops = blender::nodes::search_node_add_ops_for_basic_node;
}

View File

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BKE_node.h"
#include "BLT_translation.h"
#include "NOD_add_node_search.hh"
#include "NOD_node_declaration.hh"
namespace blender::nodes {
void GatherAddNodeSearchParams::add_item(std::string ui_name,
std::string description,
AddNodeInfo::AfterAddFn fn,
int weight)
{
r_items.append(AddNodeInfo{std::move(ui_name), std::move(description), std::move(fn), weight});
}
void search_node_add_ops_for_basic_node(GatherAddNodeSearchParams &params)
{
params.add_item(IFACE_(params.node_type().ui_name), TIP_(params.node_type().ui_description));
}
} // namespace blender::nodes

View File

@ -11,6 +11,7 @@
#include "node_shader_util.hh"
#include "NOD_add_node_search.hh"
#include "NOD_socket_search_link.hh"
#include "node_exec.h"
@ -44,6 +45,7 @@ void sh_node_type_base(struct bNodeType *ntype, int type, const char *name, shor
ntype->poll = sh_node_poll_default;
ntype->insert_link = node_insert_link_default;
ntype->gather_link_search_ops = blender::nodes::search_link_ops_for_basic_node;
ntype->gather_add_node_search_ops = blender::nodes::search_node_add_ops_for_basic_node;
}
void sh_fn_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
@ -51,6 +53,7 @@ void sh_fn_node_type_base(bNodeType *ntype, int type, const char *name, short nc
sh_node_type_base(ntype, type, name, nclass);
ntype->poll = sh_fn_poll_default;
ntype->gather_link_search_ops = blender::nodes::search_link_ops_for_basic_node;
ntype->gather_add_node_search_ops = blender::nodes::search_node_add_ops_for_basic_node;
}
/* ****** */

View File

@ -12,7 +12,9 @@
#include "node_shader_util.hh"
#include "NOD_add_node_search.hh"
#include "NOD_socket_search_link.hh"
#include "RNA_enum_types.h"
namespace blender::nodes::node_sh_mix_cc {
@ -223,6 +225,16 @@ static void node_mix_gather_link_searches(GatherLinkSearchOpParams &params)
}
}
static void gather_add_node_searches(GatherAddNodeSearchParams &params)
{
params.add_item(IFACE_("Mix"), params.node_type().ui_description);
params.add_item(IFACE_("Mix Color"),
params.node_type().ui_description,
[](const bContext & /*C*/, bNodeTree & /*node_tree*/, bNode &node) {
node_storage(node).data_type = SOCK_RGBA;
});
}
static void node_mix_init(bNodeTree * /*tree*/, bNode *node)
{
NodeShaderMix *data = MEM_cnew<NodeShaderMix>(__func__);
@ -497,5 +509,6 @@ void register_node_type_sh_mix()
ntype.draw_buttons = file_ns::sh_node_mix_layout;
ntype.labelfunc = file_ns::sh_node_mix_label;
ntype.gather_link_search_ops = file_ns::node_mix_gather_link_searches;
ntype.gather_add_node_search_ops = file_ns::gather_add_node_searches;
nodeRegisterType(&ntype);
}

View File

@ -156,5 +156,6 @@ void register_node_type_sh_mix_rgb()
ntype.gpu_fn = file_ns::gpu_shader_mix_rgb;
ntype.build_multi_function = file_ns::sh_node_mix_rgb_build_multi_function;
ntype.gather_link_search_ops = nullptr;
ntype.gather_add_node_search_ops = nullptr;
nodeRegisterType(&ntype);
}

View File

@ -40,6 +40,7 @@ void register_node_type_sh_sephsv()
ntype.declare = file_ns::node_declare_sephsv;
ntype.gpu_fn = file_ns::gpu_shader_sephsv;
ntype.gather_link_search_ops = nullptr;
ntype.gather_add_node_search_ops = nullptr;
nodeRegisterType(&ntype);
}
@ -77,6 +78,7 @@ void register_node_type_sh_combhsv()
ntype.declare = file_ns::node_declare_combhsv;
ntype.gpu_fn = file_ns::gpu_shader_combhsv;
ntype.gather_link_search_ops = nullptr;
ntype.gather_add_node_search_ops = nullptr;
nodeRegisterType(&ntype);
}

View File

@ -80,6 +80,7 @@ void register_node_type_sh_seprgb()
ntype.gpu_fn = file_ns::gpu_shader_seprgb;
ntype.build_multi_function = file_ns::sh_node_seprgb_build_multi_function;
ntype.gather_link_search_ops = nullptr;
ntype.gather_add_node_search_ops = nullptr;
nodeRegisterType(&ntype);
}
@ -125,6 +126,7 @@ void register_node_type_sh_combrgb()
ntype.gpu_fn = file_ns::gpu_shader_combrgb;
ntype.build_multi_function = file_ns::sh_node_combrgb_build_multi_function;
ntype.gather_link_search_ops = nullptr;
ntype.gather_add_node_search_ops = nullptr;
nodeRegisterType(&ntype);
}

View File

@ -36,6 +36,7 @@ void register_node_type_sh_squeeze()
sh_node_type_base(&ntype, SH_NODE_SQUEEZE, "Squeeze Value (Legacy)", NODE_CLASS_CONVERTER);
ntype.gather_link_search_ops = nullptr;
ntype.gather_add_node_search_ops = nullptr;
ntype.declare = file_ns::node_declare;
ntype.gpu_fn = file_ns::gpu_shader_squeeze;