Files
test2/source/blender/nodes/function/nodes/node_fn_replace_string.cc
Jacques Lucke 19912457c6 Nodes: use auto registration for nodes
The goal here is to reduce the number of files that need to be edited when
adding a new node. To register a node, one currently has to add a line to
`node_geometry_register.cc` and `node_geometry_register.hh` (for geometry
nodes). Those files can be generated automatically.

There is a new `NOD_REGISTER_NODE` macro that nodes can use to register
themselves. The macro is then discovered by `discover_nodes.py` that generates
code that calls all the registration functions. The script also works when the
register functions are in arbitrary namespaces. This allows simplifying the node
code as well.

In the past I tried a few times to get auto-registration working without resorting to
code generation, but that never ended up working. The general idea for that would
be to use non-trivial initialization for static variables. The issue always ends up
being that the linker just discards those variables, because they are unused and it
doesn't care if there are side effects in the initialization.

Related discussion regarding using Python for code generation:
https://devtalk.blender.org/t/code-generation-with-python/30558

Pull Request: https://projects.blender.org/blender/blender/pulls/110686
2023-08-09 22:01:03 +02:00

54 lines
1.7 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_string_utf8.h"
#include "BLI_string_utils.h"
#include "node_function_util.hh"
namespace blender::nodes::node_fn_replace_string_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::String>("String");
b.add_input<decl::String>("Find").description("The string to find in the input string");
b.add_input<decl::String>("Replace").description("The string to replace each match with");
b.add_output<decl::String>("String");
}
static std::string replace_all(const StringRefNull str,
const StringRefNull from,
const StringRefNull to)
{
if (from.is_empty()) {
return str;
}
char *new_str_ptr = BLI_string_replaceN(str.c_str(), from.c_str(), to.c_str());
std::string new_str{new_str_ptr};
MEM_freeN(new_str_ptr);
return new_str;
}
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{
static auto substring_fn = mf::build::SI3_SO<std::string, std::string, std::string, std::string>(
"Replace", [](const std::string &str, const std::string &find, const std::string &replace) {
return replace_all(str, find, replace);
});
builder.set_matching_fn(&substring_fn);
}
static void node_register()
{
static bNodeType ntype;
fn_node_type_base(&ntype, FN_NODE_REPLACE_STRING, "Replace String", NODE_CLASS_CONVERTER);
ntype.declare = node_declare;
ntype.build_multi_function = node_build_multi_function;
nodeRegisterType(&ntype);
}
NOD_REGISTER_NODE(node_register)
} // namespace blender::nodes::node_fn_replace_string_cc