diff --git a/scripts/startup/bl_ui/node_add_menu_shader.py b/scripts/startup/bl_ui/node_add_menu_shader.py index dbca8b732a1..9e020dcf482 100644 --- a/scripts/startup/bl_ui/node_add_menu_shader.py +++ b/scripts/startup/bl_ui/node_add_menu_shader.py @@ -404,6 +404,8 @@ class NODE_MT_shader_node_utilities_base(node_add_menu.NodeMenu): self.node_operator(layout, "NodeEvaluateClosure") self.node_operator(layout, "NodeCombineBundle") self.node_operator(layout, "NodeSeparateBundle") + layout.separator() + self.node_operator(layout, "GeometryNodeMenuSwitch") class NODE_MT_shader_node_all_base(node_add_menu.NodeMenu): diff --git a/source/blender/blenkernel/intern/node_tree_update.cc b/source/blender/blenkernel/intern/node_tree_update.cc index d904a82d6e4..26f5e295869 100644 --- a/source/blender/blenkernel/intern/node_tree_update.cc +++ b/source/blender/blenkernel/intern/node_tree_update.cc @@ -525,7 +525,7 @@ class NodeTreeMainUpdater { this->make_node_previews_dirty(ntree); this->propagate_runtime_flags(ntree); - if (ELEM(ntree.type, NTREE_GEOMETRY, NTREE_COMPOSIT)) { + if (ELEM(ntree.type, NTREE_GEOMETRY, NTREE_COMPOSIT, NTREE_SHADER)) { if (this->propagate_enum_definitions(ntree)) { result.interface_changed = true; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_menu_switch.cc b/source/blender/nodes/geometry/nodes/node_geo_menu_switch.cc index d284c5c66eb..763009bcb8b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_menu_switch.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_menu_switch.cc @@ -3,7 +3,9 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ #include "BLI_array_utils.hh" + #include "node_geometry_util.hh" +#include "shader/node_shader_util.hh" #include "DNA_node_types.h" @@ -553,7 +555,7 @@ static void register_node() { static blender::bke::bNodeType ntype; - geo_cmp_node_type_base(&ntype, "GeometryNodeMenuSwitch", GEO_NODE_MENU_SWITCH); + common_node_type_base(&ntype, "GeometryNodeMenuSwitch", GEO_NODE_MENU_SWITCH); ntype.ui_name = "Menu Switch"; ntype.ui_description = "Select from multiple inputs by name"; ntype.enum_name_legacy = "MENU_SWITCH"; diff --git a/source/blender/nodes/intern/shader_nodes_inline.cc b/source/blender/nodes/intern/shader_nodes_inline.cc index 482fdd45178..4637af091c7 100644 --- a/source/blender/nodes/intern/shader_nodes_inline.cc +++ b/source/blender/nodes/intern/shader_nodes_inline.cc @@ -14,6 +14,7 @@ #include "BLI_math_vector.h" #include "BLI_stack.hh" +#include "NOD_menu_value.hh" #include "NOD_multi_function.hh" #include "NOD_node_declaration.hh" #include "NOD_node_in_compute_context.hh" @@ -33,7 +34,7 @@ struct NodeAndSocket { }; struct PrimitiveSocketValue { - std::variant value; + std::variant value; const void *buffer() const { @@ -63,6 +64,9 @@ struct PrimitiveSocketValue { if (type.is()) { return {*static_cast(value.get())}; } + if (type.is()) { + return {*static_cast(value.get())}; + } BLI_assert_unreachable(); return {}; } @@ -127,6 +131,9 @@ struct SocketValue { case SOCK_RGBA: return PrimitiveSocketValue{ ColorGeometry4f(socket.default_value_typed()->value)}; + case SOCK_MENU: + return PrimitiveSocketValue{ + MenuValue(socket.default_value_typed()->value)}; default: return std::nullopt; } @@ -438,6 +445,10 @@ class ShaderNodesInliner { this->handle_output_socket__separate_bundle(socket); return; } + if (node->is_type("GeometryNodeMenuSwitch")) { + this->handle_output_socket__menu_switch(socket); + return; + } this->handle_output_socket__eval(socket); } @@ -852,6 +863,53 @@ class ShaderNodesInliner { this->store_socket_value_fallback(socket); } + void handle_output_socket__menu_switch(const SocketInContext &socket) + { + const NodeInContext node = socket.owner_node(); + const auto &storage = *static_cast(node->storage); + + const SocketInContext menu_input = node.input_socket(0); + const SocketValue *menu_socket_value = value_by_socket_.lookup_ptr(menu_input); + if (!menu_socket_value) { + /* The menu value is not known yet, so schedule it for now. */ + this->schedule_socket(menu_input); + return; + } + + const std::optional menu_value_opt = menu_socket_value->to_primitive( + *menu_input->typeinfo); + if (!menu_value_opt) { + /* This limitation may be lifted in the future. Menu Switch nodes could be supported natively + * by render engines or we convert them to a bunch of mix nodes. */ + this->store_socket_value_fallback(socket); + params_.r_error_messages.append({node.node, TIP_("Menu value has to be a constant value")}); + return; + } + const MenuValue menu_value = std::get(menu_value_opt->value); + /* Find the selected item index. */ + std::optional selected_index; + for (const int item_i : IndexRange(storage.enum_definition.items_num)) { + const NodeEnumItem &item = storage.enum_definition.items_array[item_i]; + if (MenuValue(item.identifier) == menu_value) { + selected_index = item_i; + break; + } + } + if (!selected_index.has_value()) { + /* The input value does not exist in the menu. */ + this->store_socket_value_fallback(socket); + return; + } + if (socket->index() == 0) { + /* Handle forwarding the selected value. */ + this->forward_value_or_schedule(socket, node.input_socket(*selected_index + 1)); + return; + } + /* Set the value of the mask output. */ + const bool is_selected = selected_index == socket->index() - 1; + this->store_socket_value(socket, {PrimitiveSocketValue{is_selected}}); + } + /** * Evaluate a node to compute the value of the given output socket. This may also compute all the * other outputs of the node. diff --git a/source/blender/nodes/shader/node_shader_tree.cc b/source/blender/nodes/shader/node_shader_tree.cc index 13c308479b7..7701249105e 100644 --- a/source/blender/nodes/shader/node_shader_tree.cc +++ b/source/blender/nodes/shader/node_shader_tree.cc @@ -158,7 +158,9 @@ static bool shader_validate_link(eNodeSocketDatatype from, eNodeSocketDatatype t if (from == SOCK_SHADER) { return to == SOCK_SHADER; } - if (ELEM(to, SOCK_BUNDLE, SOCK_CLOSURE) || ELEM(from, SOCK_BUNDLE, SOCK_CLOSURE)) { + if (ELEM(to, SOCK_BUNDLE, SOCK_CLOSURE, SOCK_MENU) || + ELEM(from, SOCK_BUNDLE, SOCK_CLOSURE, SOCK_MENU)) + { return from == to; } return true; @@ -175,7 +177,8 @@ static bool shader_node_tree_socket_type_valid(blender::bke::bNodeTreeType * /*n SOCK_RGBA, SOCK_SHADER, SOCK_BUNDLE, - SOCK_CLOSURE); + SOCK_CLOSURE, + SOCK_MENU); } blender::bke::bNodeTreeType *ntreeType_Shader; diff --git a/tests/files/render/node_inlining/cycles_renders/menu_socket.png b/tests/files/render/node_inlining/cycles_renders/menu_socket.png new file mode 100644 index 00000000000..74065daa575 --- /dev/null +++ b/tests/files/render/node_inlining/cycles_renders/menu_socket.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:151b757666c47a41b582a74a651074323151974f720d74cb1e429f22c0f6a3a6 +size 7826 diff --git a/tests/files/render/node_inlining/eevee_renders/menu_socket.png b/tests/files/render/node_inlining/eevee_renders/menu_socket.png new file mode 100644 index 00000000000..e700d3830ca --- /dev/null +++ b/tests/files/render/node_inlining/eevee_renders/menu_socket.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ebc572c8ec18924c982b4cd2b6497af8707c6f680ed9aa4e7cb9a1b9e83d0f9e +size 4911 diff --git a/tests/files/render/node_inlining/menu_socket.blend b/tests/files/render/node_inlining/menu_socket.blend new file mode 100644 index 00000000000..67e5234f13e --- /dev/null +++ b/tests/files/render/node_inlining/menu_socket.blend @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a80a6c5e1458bb95af42f3369d8b4c8b8d6934274e4e20c3fb6929a276d47842 +size 949808 diff --git a/tests/files/render/node_inlining/storm_hydra_renders/menu_socket.png b/tests/files/render/node_inlining/storm_hydra_renders/menu_socket.png new file mode 100644 index 00000000000..c9fae13193b --- /dev/null +++ b/tests/files/render/node_inlining/storm_hydra_renders/menu_socket.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dfebf6e15a866ad68f568dd2b311d26ba72264932ade485209b62eb3ce383a07 +size 3181 diff --git a/tests/files/render/node_inlining/storm_usd_renders/menu_socket.png b/tests/files/render/node_inlining/storm_usd_renders/menu_socket.png new file mode 100644 index 00000000000..77bc12ae15d --- /dev/null +++ b/tests/files/render/node_inlining/storm_usd_renders/menu_socket.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1002034f40f22b6242b947a5d9b3af189046cfa4ce61b72c85d5947d9df89f6 +size 3181 diff --git a/tests/files/render/node_inlining/workbench_renders/menu_socket.png b/tests/files/render/node_inlining/workbench_renders/menu_socket.png new file mode 100644 index 00000000000..9196b7428f4 --- /dev/null +++ b/tests/files/render/node_inlining/workbench_renders/menu_socket.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ef01a01e7d6e1b63e25a85d3bae3959f111393a1c167ebc416f6191cf0958f2 +size 1787