Geometry Nodes: use dynamic declaration for switch node #113413

Merged
Hans Goudey merged 7 commits from JacquesLucke/blender:switch-dynamic-declaration into main 2023-12-13 17:33:35 +01:00
4 changed files with 50 additions and 147 deletions

View File

@ -1768,6 +1768,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;
@ -2578,6 +2589,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");

Is there the chance to note the type of value in anythere?

Is there the chance to note the type of value in anythere?
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)
{
mod_moder marked this conversation as resolved

Can part of function be replaced by search_link_ops_for_declarations(params, params.node_type().static_declaration->inputs);?

Can part of function be replaced by `search_link_ops_for_declarations(params, params.node_type().static_declaration->inputs);`?
Review

Not yet, since we don't handle multiple types like that for link drag search yet

Not yet, since we don't handle multiple types like that for link drag search yet

Ah yes, boolean a switch input is dynamic too!

Ah yes, boolean a switch input is dynamic too!
if (params.in_out() == SOCK_OUT) {
@ -297,7 +238,6 @@ static void node_rna(StructRNA *srna)
SOCK_GEOMETRY,
SOCK_OBJECT,
SOCK_COLLECTION,
SOCK_TEXTURE,
mod_moder marked this conversation as resolved Outdated

Unrelated change?

Unrelated change?

Required to not assert when switching to texture type in the UI enum. It's not supported anyway in geometry nodes, pure legacy stuff.

Required to not assert when switching to texture type in the UI enum. It's not supported anyway in geometry nodes, pure legacy stuff.
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);
}