Geometry Nodes: use dynamic declaration for switch node

Follow up for 8149678d5e. Significantly reduce boilerplate
required for each type in the switch node.Forward compatibility in 4.0
provided by 0ea193bdb3.

Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/113413
This commit is contained in:
Jacques Lucke 2023-12-13 17:33:25 +01:00 committed by Hans Goudey
parent 65252564ee
commit f7383cfe9b
4 changed files with 50 additions and 147 deletions

View File

@ -1766,6 +1766,17 @@ static void versioning_nodes_dynamic_sockets(bNodeTree &ntree)
}
}
static void versioning_switch_node_dynamic_socket(bNodeTree &ntree)
{
LISTBASE_FOREACH (bNode *, node, &ntree.nodes) {
if (node->type != GEO_NODE_SWITCH) {
continue;
}
version_socket_identifier_suffixes_for_dynamic_types(node->inputs, "_");
version_socket_identifier_suffixes_for_dynamic_types(node->outputs, "_");
}
}
static void versioning_grease_pencil_stroke_radii_scaling(GreasePencil *grease_pencil)
{
using namespace blender;
@ -2576,6 +2587,7 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
if (ntree->type == NTREE_GEOMETRY) {
version_geometry_nodes_use_rotation_socket(*ntree);
versioning_switch_node_dynamic_socket(*ntree);
}
}
}

View File

@ -19,55 +19,27 @@ NODE_STORAGE_FUNCS(NodeSwitch)
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Bool>("Switch").default_value(false).supports_field();
b.add_input<decl::Bool>("Switch", "Switch_001").default_value(false);
auto &switch_decl = b.add_input<decl::Bool>("Switch");
const bNode *node = b.node_or_null();
if (!node) {
return;
}
const NodeSwitch &storage = node_storage(*node);
const eNodeSocketDatatype socket_type = eNodeSocketDatatype(storage.input_type);
b.add_input<decl::Float>("False").supports_field();
b.add_input<decl::Float>("True").supports_field();
b.add_input<decl::Int>("False", "False_001").min(-100000).max(100000).supports_field();
b.add_input<decl::Int>("True", "True_001").min(-100000).max(100000).supports_field();
b.add_input<decl::Bool>("False", "False_002").default_value(false).hide_value().supports_field();
b.add_input<decl::Bool>("True", "True_002").default_value(true).hide_value().supports_field();
b.add_input<decl::Vector>("False", "False_003").supports_field();
b.add_input<decl::Vector>("True", "True_003").supports_field();
auto &false_decl = b.add_input(socket_type, "False");
auto &true_decl = b.add_input(socket_type, "True");
auto &output_decl = b.add_output(socket_type, "Output");
b.add_input<decl::Color>("False", "False_004")
.default_value({0.8f, 0.8f, 0.8f, 1.0f})
.supports_field();
b.add_input<decl::Color>("True", "True_004")
.default_value({0.8f, 0.8f, 0.8f, 1.0f})
.supports_field();
b.add_input<decl::String>("False", "False_005").supports_field();
b.add_input<decl::String>("True", "True_005").supports_field();
b.add_input<decl::Geometry>("False", "False_006");
b.add_input<decl::Geometry>("True", "True_006");
b.add_input<decl::Object>("False", "False_007");
b.add_input<decl::Object>("True", "True_007");
b.add_input<decl::Collection>("False", "False_008");
b.add_input<decl::Collection>("True", "True_008");
b.add_input<decl::Texture>("False", "False_009");
b.add_input<decl::Texture>("True", "True_009");
b.add_input<decl::Material>("False", "False_010");
b.add_input<decl::Material>("True", "True_010");
b.add_input<decl::Image>("False", "False_011");
b.add_input<decl::Image>("True", "True_011");
b.add_input<decl::Rotation>("False", "False_012").supports_field();
b.add_input<decl::Rotation>("True", "True_012").supports_field();
b.add_output<decl::Float>("Output").dependent_field().reference_pass_all();
b.add_output<decl::Int>("Output", "Output_001").dependent_field().reference_pass_all();
b.add_output<decl::Bool>("Output", "Output_002").dependent_field().reference_pass_all();
b.add_output<decl::Vector>("Output", "Output_003").dependent_field().reference_pass_all();
b.add_output<decl::Color>("Output", "Output_004").dependent_field().reference_pass_all();
b.add_output<decl::String>("Output", "Output_005").dependent_field().reference_pass_all();
b.add_output<decl::Geometry>("Output", "Output_006").propagate_all();
b.add_output<decl::Object>("Output", "Output_007");
b.add_output<decl::Collection>("Output", "Output_008");
b.add_output<decl::Texture>("Output", "Output_009");
b.add_output<decl::Material>("Output", "Output_010");
b.add_output<decl::Image>("Output", "Output_011");
b.add_output<decl::Rotation>("Output", "Output_012").propagate_all().reference_pass_all();
if (socket_type_supports_fields(socket_type)) {
switch_decl.supports_field();
false_decl.supports_field();
true_decl.supports_field();
output_decl.dependent_field().reference_pass_all();
}
if (socket_type == SOCK_GEOMETRY) {
output_decl.propagate_all();
}
}
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
@ -82,37 +54,6 @@ static void node_init(bNodeTree * /*tree*/, bNode *node)
node->storage = data;
}
static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeSwitch &storage = node_storage(*node);
int index = 0;
bNodeSocket *field_switch = static_cast<bNodeSocket *>(node->inputs.first);
bNodeSocket *non_field_switch = static_cast<bNodeSocket *>(field_switch->next);
const bool fields_type = ELEM(storage.input_type,
SOCK_FLOAT,
SOCK_INT,
SOCK_BOOLEAN,
SOCK_VECTOR,
SOCK_RGBA,
SOCK_STRING,
SOCK_ROTATION);
bke::nodeSetSocketAvailability(ntree, field_switch, fields_type);
bke::nodeSetSocketAvailability(ntree, non_field_switch, !fields_type);
LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, &node->inputs, index) {
if (index <= 1) {
continue;
}
bke::nodeSetSocketAvailability(ntree, socket, socket->type == storage.input_type);
}
LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) {
bke::nodeSetSocketAvailability(ntree, socket, socket->type == storage.input_type);
}
}
static void node_gather_link_searches(GatherLinkSearchOpParams &params)
{
if (params.in_out() == SOCK_OUT) {
@ -297,7 +238,6 @@ static void node_rna(StructRNA *srna)
SOCK_GEOMETRY,
SOCK_OBJECT,
SOCK_COLLECTION,
SOCK_TEXTURE,
SOCK_MATERIAL,
SOCK_IMAGE);
});
@ -311,7 +251,6 @@ static void register_node()
geo_node_type_base(&ntype, GEO_NODE_SWITCH, "Switch", NODE_CLASS_CONVERTER);
ntype.declare = node_declare;
ntype.initfunc = node_init;
ntype.updatefunc = node_update;
node_type_storage(&ntype, "NodeSwitch", node_free_standard_storage, node_copy_standard_storage);
ntype.gather_link_search_ops = node_gather_link_searches;
ntype.draw_buttons = node_layout;

View File

@ -3524,73 +3524,43 @@ struct GeometryNodesLazyFunctionBuilder {
lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
scope_.add(std::move(lazy_function));
int input_index = 0;
for (const bNodeSocket *bsocket : bnode.input_sockets()) {
if (bsocket->is_available()) {
lf::InputSocket &lf_socket = lf_node.input(input_index);
graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
mapping_->bsockets_by_lf_socket_map.add(&lf_socket, bsocket);
input_index++;
}
}
for (const bNodeSocket *bsocket : bnode.output_sockets()) {
if (bsocket->is_available()) {
lf::OutputSocket &lf_socket = lf_node.output(0);
graph_params.lf_output_by_bsocket.add(bsocket, &lf_socket);
mapping_->bsockets_by_lf_socket_map.add(&lf_socket, bsocket);
break;
}
for (const int i : bnode.input_sockets().index_range()) {
graph_params.lf_inputs_by_bsocket.add(&bnode.input_socket(i), &lf_node.input(i));
mapping_->bsockets_by_lf_socket_map.add(&lf_node.input(i), &bnode.input_socket(i));
}
graph_params.lf_output_by_bsocket.add(&bnode.output_socket(0), &lf_node.output(0));
mapping_->bsockets_by_lf_socket_map.add(&lf_node.output(0), &bnode.output_socket(0));
this->build_switch_node_socket_usage(bnode, graph_params);
}
void build_switch_node_socket_usage(const bNode &bnode, BuildGraphParams &graph_params)
{
const bNodeSocket *switch_input_bsocket = nullptr;
const bNodeSocket *false_input_bsocket = nullptr;
const bNodeSocket *true_input_bsocket = nullptr;
const bNodeSocket *output_bsocket = nullptr;
for (const bNodeSocket *socket : bnode.input_sockets()) {
if (!socket->is_available()) {
continue;
}
if (socket->name == StringRef("Switch")) {
switch_input_bsocket = socket;
}
else if (socket->name == StringRef("False")) {
false_input_bsocket = socket;
}
else if (socket->name == StringRef("True")) {
true_input_bsocket = socket;
}
}
for (const bNodeSocket *socket : bnode.output_sockets()) {
if (socket->is_available()) {
output_bsocket = socket;
break;
}
}
const bNodeSocket &switch_input_bsocket = bnode.input_socket(0);
const bNodeSocket &false_input_bsocket = bnode.input_socket(1);
const bNodeSocket &true_input_bsocket = bnode.input_socket(2);
const bNodeSocket &output_bsocket = bnode.output_socket(0);
lf::OutputSocket *output_is_used_socket = graph_params.usage_by_bsocket.lookup_default(
output_bsocket, nullptr);
&output_bsocket, nullptr);
if (output_is_used_socket == nullptr) {
return;
}
graph_params.usage_by_bsocket.add(switch_input_bsocket, output_is_used_socket);
if (switch_input_bsocket->is_directly_linked()) {
graph_params.usage_by_bsocket.add(&switch_input_bsocket, output_is_used_socket);
if (switch_input_bsocket.is_directly_linked()) {
/* The condition input is dynamic, so the usage of the other inputs is as well. */
static const LazyFunctionForSwitchSocketUsage switch_socket_usage_fn;
lf::Node &lf_node = graph_params.lf_graph.add_function(switch_socket_usage_fn);
graph_params.lf_inputs_by_bsocket.add(switch_input_bsocket, &lf_node.input(0));
graph_params.usage_by_bsocket.add(false_input_bsocket, &lf_node.output(0));
graph_params.usage_by_bsocket.add(true_input_bsocket, &lf_node.output(1));
graph_params.lf_inputs_by_bsocket.add(&switch_input_bsocket, &lf_node.input(0));
graph_params.usage_by_bsocket.add(&false_input_bsocket, &lf_node.output(0));
graph_params.usage_by_bsocket.add(&true_input_bsocket, &lf_node.output(1));
}
else {
if (switch_input_bsocket->default_value_typed<bNodeSocketValueBoolean>()->value) {
graph_params.usage_by_bsocket.add(true_input_bsocket, output_is_used_socket);
if (switch_input_bsocket.default_value_typed<bNodeSocketValueBoolean>()->value) {
graph_params.usage_by_bsocket.add(&true_input_bsocket, output_is_used_socket);
}
else {
graph_params.usage_by_bsocket.add(false_input_bsocket, output_is_used_socket);
graph_params.usage_by_bsocket.add(&false_input_bsocket, output_is_used_socket);
}
}
}

View File

@ -371,24 +371,6 @@ static const char *get_current_socket_identifier_for_future_socket(
const Span<const SocketDeclaration *> socket_decls)
{
switch (node.type) {
case GEO_NODE_SWITCH: {
const NodeSwitch &storage = *static_cast<const NodeSwitch *>(node.storage);
const bool use_field_socket = ELEM(storage.input_type,
SOCK_FLOAT,
SOCK_INT,
SOCK_BOOLEAN,
SOCK_VECTOR,
SOCK_RGBA,
SOCK_STRING,
SOCK_ROTATION);
if (BLI_str_startswith(socket.identifier, "Switch")) {
if (use_field_socket) {
return "Switch";
}
return "Switch_001";
}
return get_identifier_from_decl({"False", "True", "Output"}, socket, socket_decls);
}
case GEO_NODE_SAMPLE_CURVE: {
return get_identifier_from_decl("Value", socket, socket_decls);
}