Compositor: Replace Switch node with Geometry Nodes'

This patch replaces the Switch node in the compositor with the Switch
node from Geometry Nodes. The node gained a new type input. The old node
was marked deprecated and will be removed in a future version.

Pull Request: https://projects.blender.org/blender/blender/pulls/158744
This commit is contained in:
Omar Emara 2026-05-20 16:01:57 +02:00 • committed by Omar Emara
parent 71e8f2f21e
commit ca2588ada0
6 changed files with 85 additions and 11 deletions

View file

@ -300,7 +300,7 @@ class NODE_MT_compositor_node_utilities_base(node_add_menu.NodeMenu):
layout.separator()
self.node_operator(layout, "NodeImplicitConversion")
self.node_operator(layout, "CompositorNodeSplit")
self.node_operator(layout, "CompositorNodeSwitch")
self.node_operator(layout, "GeometryNodeSwitch")
self.node_operator(layout, "GeometryNodeIndexSwitch")
self.node_operator(layout, "GeometryNodeMenuSwitch")
self.node_operator(

View file

@ -30,7 +30,7 @@ namespace blender {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 33
#define BLENDER_FILE_SUBVERSION 34
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and cancel loading the file, showing a warning to

View file

@ -22,6 +22,7 @@
#include "BLI_listbase_iterator.hh"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_string_utils.hh"
#include "BLI_sys_types.h"
@ -384,6 +385,23 @@ static void enable_compositor_nodes_is_strip_modifier(Main &bmain)
}
}
static void versioning_replace_legacy_compositor_switch_node(bNodeTree *node_tree)
{
version_node_input_socket_name(node_tree, CMP_NODE_SWITCH, "On", "True");
version_node_input_socket_name(node_tree, CMP_NODE_SWITCH, "Off", "False");
version_node_output_socket_name(node_tree, CMP_NODE_SWITCH, "Image", "Output");
for (bNode &node : node_tree->nodes) {
if (node.type_legacy == CMP_NODE_SWITCH) {
node.type_legacy = GEO_NODE_SWITCH;
NodeSwitch *storage = MEM_new<NodeSwitch>(__func__);
storage->input_type = SOCK_RGBA;
STRNCPY_UTF8(node.idname, "GeometryNodeSwitch");
node.storage = storage;
}
}
}
void do_versions_after_linking_520(FileData *fd, Main *bmain)
{
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 502, 2)) {
@ -698,6 +716,16 @@ void blo_do_versions_520(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
}
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 502, 34)) {
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
if (ntree->type == NTREE_COMPOSIT) {
versioning_replace_legacy_compositor_switch_node(ntree);
}
}
FOREACH_NODETREE_END;
}
/**
* Always bump subversion in BKE_blender_version.h when adding versioning
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.

View file

@ -223,7 +223,7 @@ static bool is_switch_node_input_needed(const bNode &node,
return true;
}
return (input.identifier_ustr() == "On"_ustr) == condition.value();
return (input.identifier_ustr() == "True"_ustr) == condition.value();
}
/* returns true if the given input of the given menu switch node in the given node group operation
@ -287,7 +287,7 @@ static bool is_input_needed(const bNode &node,
return node_group_operation.get_result(input.identifier).should_compute();
}
if (node.is_type("CompositorNodeSwitch"_ustr)) {
if (node.is_type("GeometryNodeSwitch"_ustr)) {
return is_switch_node_input_needed(node, input, node_group_operation);
}

View file

@ -58,6 +58,7 @@ static void node_register()
ntype.nclass = NODE_CLASS_CONVERTER;
ntype.declare = node_declare;
ntype.get_compositor_operation = get_compositor_operation;
ntype.deprecation_notice = N_("Use Utilities \u25B8 Switch node instead");
bke::node_register_type(ntype);
}

View file

@ -15,6 +15,9 @@
#include "RNA_enum_types.hh"
#include "COM_node_operation.hh"
#include "COM_utilities.hh"
#include "FN_multi_function_builder.hh"
namespace blender {
@ -26,8 +29,9 @@ NODE_STORAGE_FUNCS(NodeSwitch)
static void node_declare(NodeDeclarationBuilder &b)
{
auto &switch_decl = b.add_input<decl::Bool>("Switch"_ustr);
const bNodeTree *node_tree = b.tree_or_null();
const bNode *node = b.node_or_null();
if (!node) {
if (!node_tree || !node) {
return;
}
const NodeSwitch &storage = node_storage(*node);
@ -37,7 +41,7 @@ static void node_declare(NodeDeclarationBuilder &b)
auto &true_decl = b.add_input(socket_type, "True"_ustr);
auto &output_decl = b.add_output(socket_type, "Output"_ustr);
if (socket_type_supports_attributes(socket_type)) {
if (socket_type_supports_attributes(socket_type) && node_tree->type == NTREE_GEOMETRY) {
switch_decl.supports_field();
false_decl.supports_field();
true_decl.supports_field();
@ -50,10 +54,25 @@ static void node_declare(NodeDeclarationBuilder &b)
output_decl.reference_pass_all();
}
switch_decl.structure_type(StructureType::Dynamic);
false_decl.structure_type(StructureType::Dynamic);
true_decl.structure_type(StructureType::Dynamic);
output_decl.structure_type(StructureType::Dynamic);
StructureType value_structure_type = StructureType::Dynamic;
StructureType condition_structure_type = StructureType::Dynamic;
if (node_tree->type == NTREE_COMPOSIT) {
const bool is_single_compositor_type = compositor::Result::is_single_value_only_type(
compositor::socket_data_type_to_result_type(socket_type));
if (is_single_compositor_type) {
value_structure_type = StructureType::Single;
}
condition_structure_type = StructureType::Single;
false_decl.compositor_realization_mode(CompositorInputRealizationMode::None);
true_decl.compositor_realization_mode(CompositorInputRealizationMode::None);
}
switch_decl.structure_type(condition_structure_type);
false_decl.structure_type(value_structure_type);
true_decl.structure_type(value_structure_type);
output_decl.structure_type(value_structure_type);
}
static void node_layout(ui::Layout &layout, bContext * /*C*/, PointerRNA *ptr)
@ -232,6 +251,30 @@ class LazyFunctionForSwitchNode : public LazyFunction {
}
};
using namespace blender::compositor;
class SwitchOperation : public NodeOperation {
public:
using NodeOperation::NodeOperation;
void execute() override
{
const Result &input = this->get_input(this->get_condition() ? "True" : "False");
Result &output = this->get_result("Output");
output.share_data(input);
}
bool get_condition()
{
return this->get_input("Switch").get_single_value_default<bool>();
}
};
static NodeOperation *get_compositor_operation(Context &context, const bNode &node)
{
return new SwitchOperation(context, node);
}
static const bNodeSocket *node_internally_linked_input(const bNodeTree & /*tree*/,
const bNode &node,
const bNodeSocket & /*output_socket*/)
@ -265,7 +308,7 @@ static void register_node()
{
static bke::bNodeType ntype;
geo_node_type_base(&ntype, "GeometryNodeSwitch"_ustr, GEO_NODE_SWITCH);
geo_cmp_node_type_base(&ntype, "GeometryNodeSwitch"_ustr, GEO_NODE_SWITCH);
ntype.ui_name = "Switch";
ntype.ui_description = "Switch between two inputs";
ntype.enum_name_legacy = "SWITCH";
@ -278,6 +321,8 @@ static void register_node()
ntype.draw_buttons = node_layout;
ntype.ignore_inferred_input_socket_visibility = true;
ntype.internally_linked_input = node_internally_linked_input;
ntype.get_compositor_operation = get_compositor_operation;
bke::node_register_type(ntype);
node_rna(ntype.rna_ext.srna);