Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_switch.cc
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||||
| #include "node_geometry_util.hh" | #include "node_geometry_util.hh" | ||||
| #include "UI_interface.h" | #include "UI_interface.h" | ||||
| #include "UI_resources.h" | #include "UI_resources.h" | ||||
| #include "DNA_mesh_types.h" | #include "DNA_mesh_types.h" | ||||
| #include "DNA_meshdata_types.h" | #include "DNA_meshdata_types.h" | ||||
| #include "BKE_attribute_math.hh" | |||||
| #include "BKE_material.h" | #include "BKE_material.h" | ||||
| #include "NOD_socket_search_link.hh" | #include "NOD_socket_search_link.hh" | ||||
| #include "FN_multi_function_signature.hh" | #include "FN_multi_function_signature.hh" | ||||
| namespace blender::nodes::node_geo_switch_cc { | namespace blender::nodes::node_geo_switch_cc { | ||||
| NODE_STORAGE_FUNCS(NodeSwitch) | NODE_STORAGE_FUNCS(NodeSwitch) | ||||
| static void node_declare(NodeDeclarationBuilder &b) | static void node_declare(NodeDeclarationBuilder &b) | ||||
| { | { | ||||
| b.add_input<decl::Bool>(N_("Switch")).default_value(false).supports_field(); | b.add_input<decl::Bool>(N_("Switch"), "Switch_Field").default_value(false).supports_field(); | ||||
| b.add_input<decl::Bool>(N_("Switch"), "Switch_001").default_value(false); | b.add_input<decl::Bool>(N_("Switch"), "Switch_Single").default_value(false); | ||||
| b.add_input<decl::Float>(N_("False")).supports_field(); | b.add_input<decl::Float>(N_("False"), "False_Float").supports_field(); | ||||
| b.add_input<decl::Float>(N_("True")).supports_field(); | b.add_input<decl::Float>(N_("True"), "True_Float").supports_field(); | ||||
| b.add_input<decl::Int>(N_("False"), "False_001").min(-100000).max(100000).supports_field(); | b.add_input<decl::Int>(N_("False"), "False_Int").min(-100000).max(100000).supports_field(); | ||||
| b.add_input<decl::Int>(N_("True"), "True_001").min(-100000).max(100000).supports_field(); | b.add_input<decl::Int>(N_("True"), "True_Int").min(-100000).max(100000).supports_field(); | ||||
| b.add_input<decl::Bool>(N_("False"), "False_002") | b.add_input<decl::Bool>(N_("False"), "False_Bool").default_value(false).supports_field(); | ||||
| .default_value(false) | b.add_input<decl::Bool>(N_("True"), "True_Bool").default_value(true).supports_field(); | ||||
| .hide_value() | b.add_input<decl::Vector>(N_("False"), "False_Vector").supports_field(); | ||||
| .supports_field(); | b.add_input<decl::Vector>(N_("True"), "True_Vector").supports_field(); | ||||
| b.add_input<decl::Bool>(N_("True"), "True_002") | b.add_input<decl::Color>(N_("False"), "False_Color") | ||||
| .default_value(true) | |||||
| .hide_value() | |||||
| .supports_field(); | |||||
| b.add_input<decl::Vector>(N_("False"), "False_003").supports_field(); | |||||
| b.add_input<decl::Vector>(N_("True"), "True_003").supports_field(); | |||||
| b.add_input<decl::Color>(N_("False"), "False_004") | |||||
| .default_value({0.8f, 0.8f, 0.8f, 1.0f}) | .default_value({0.8f, 0.8f, 0.8f, 1.0f}) | ||||
| .supports_field(); | .supports_field(); | ||||
| b.add_input<decl::Color>(N_("True"), "True_004") | b.add_input<decl::Color>(N_("True"), "True_Color") | ||||
| .default_value({0.8f, 0.8f, 0.8f, 1.0f}) | .default_value({0.8f, 0.8f, 0.8f, 1.0f}) | ||||
| .supports_field(); | .supports_field(); | ||||
| b.add_input<decl::String>(N_("False"), "False_005").supports_field(); | b.add_input<decl::String>(N_("False"), "False_String").supports_field(); | ||||
| b.add_input<decl::String>(N_("True"), "True_005").supports_field(); | b.add_input<decl::String>(N_("True"), "Strue_String").supports_field(); | ||||
| b.add_input<decl::Geometry>(N_("False"), "False_006"); | b.add_input<decl::Geometry>(N_("False"), "False_Geometry"); | ||||
| b.add_input<decl::Geometry>(N_("True"), "True_006"); | b.add_input<decl::Geometry>(N_("True"), "True_Geometry"); | ||||
| b.add_input<decl::Object>(N_("False"), "False_007"); | b.add_input<decl::Object>(N_("False"), "False_Object"); | ||||
| b.add_input<decl::Object>(N_("True"), "True_007"); | b.add_input<decl::Object>(N_("True"), "True_Object"); | ||||
| b.add_input<decl::Collection>(N_("False"), "False_008"); | b.add_input<decl::Collection>(N_("False"), "False_Collection"); | ||||
| b.add_input<decl::Collection>(N_("True"), "True_008"); | b.add_input<decl::Collection>(N_("True"), "True_Collection"); | ||||
| b.add_input<decl::Texture>(N_("False"), "False_009"); | b.add_input<decl::Texture>(N_("False"), "False_Texture"); | ||||
| b.add_input<decl::Texture>(N_("True"), "True_009"); | b.add_input<decl::Texture>(N_("True"), "True_Texture"); | ||||
| b.add_input<decl::Material>(N_("False"), "False_010"); | b.add_input<decl::Material>(N_("False"), "False_Material"); | ||||
| b.add_input<decl::Material>(N_("True"), "True_010"); | b.add_input<decl::Material>(N_("True"), "True_Material"); | ||||
| b.add_input<decl::Image>(N_("False"), "False_011"); | b.add_input<decl::Image>(N_("False"), "False_Image"); | ||||
| b.add_input<decl::Image>(N_("True"), "True_011"); | b.add_input<decl::Image>(N_("True"), "True_Image"); | ||||
| b.add_output<decl::Float>(N_("Output")).dependent_field(); | b.add_output<decl::Float>(N_("Output"), "Float").dependent_field(); | ||||
| b.add_output<decl::Int>(N_("Output"), "Output_001").dependent_field(); | b.add_output<decl::Int>(N_("Output"), "Int").dependent_field(); | ||||
| b.add_output<decl::Bool>(N_("Output"), "Output_002").dependent_field(); | b.add_output<decl::Bool>(N_("Output"), "Bool").dependent_field(); | ||||
| b.add_output<decl::Vector>(N_("Output"), "Output_003").dependent_field(); | b.add_output<decl::Vector>(N_("Output"), "Vector").dependent_field(); | ||||
| b.add_output<decl::Color>(N_("Output"), "Output_004").dependent_field(); | b.add_output<decl::Color>(N_("Output"), "Color").dependent_field(); | ||||
| b.add_output<decl::String>(N_("Output"), "Output_005").dependent_field(); | b.add_output<decl::String>(N_("Output"), "String").dependent_field(); | ||||
| b.add_output<decl::Geometry>(N_("Output"), "Output_006"); | b.add_output<decl::Geometry>(N_("Output"), "Geometry"); | ||||
| b.add_output<decl::Object>(N_("Output"), "Output_007"); | b.add_output<decl::Object>(N_("Output"), "Object"); | ||||
| b.add_output<decl::Collection>(N_("Output"), "Output_008"); | b.add_output<decl::Collection>(N_("Output"), "Collection"); | ||||
| b.add_output<decl::Texture>(N_("Output"), "Output_009"); | b.add_output<decl::Texture>(N_("Output"), "Texture"); | ||||
| b.add_output<decl::Material>(N_("Output"), "Output_010"); | b.add_output<decl::Material>(N_("Output"), "Material"); | ||||
| b.add_output<decl::Image>(N_("Output"), "Output_011"); | b.add_output<decl::Image>(N_("Output"), "Image"); | ||||
| } | } | ||||
| static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) | static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) | ||||
| { | { | ||||
| uiItemR(layout, ptr, "input_type", 0, "", ICON_NONE); | uiItemR(layout, ptr, "input_type", 0, "", ICON_NONE); | ||||
| } | } | ||||
| static void node_init(bNodeTree *UNUSED(tree), bNode *node) | static void node_init(bNodeTree *UNUSED(tree), bNode *node) | ||||
| ▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | else { | ||||
| params.add_item(IFACE_("True"), [](LinkSearchOpParams ¶ms) { | params.add_item(IFACE_("True"), [](LinkSearchOpParams ¶ms) { | ||||
| bNode &node = params.add_node("GeometryNodeSwitch"); | bNode &node = params.add_node("GeometryNodeSwitch"); | ||||
| node_storage(node).input_type = params.socket.type; | node_storage(node).input_type = params.socket.type; | ||||
| params.update_and_connect_available_socket(node, "True"); | params.update_and_connect_available_socket(node, "True"); | ||||
| }); | }); | ||||
| } | } | ||||
| } | } | ||||
| template<typename T> void switch_fields(GeoNodeExecParams ¶ms, const StringRef suffix) | template<typename T> void switch_fields(GeoNodeExecParams ¶ms) | ||||
| { | { | ||||
| if (params.lazy_require_input("Switch")) { | if (params.lazy_require_input("Switch_Field")) { | ||||
| return; | return; | ||||
| } | } | ||||
| const std::string name_false = "False" + suffix; | const std::string name_false = "False_" + attribute_math::default_name<T>(); | ||||
| const std::string name_true = "True" + suffix; | const std::string name_true = "True_" + attribute_math::default_name<T>(); | ||||
| const std::string name_output = "Output" + suffix; | |||||
| Field<bool> switches_field = params.get_input<Field<bool>>("Switch_Field"); | |||||
| Field<bool> switches_field = params.get_input<Field<bool>>("Switch"); | |||||
| if (switches_field.node().depends_on_input()) { | if (switches_field.node().depends_on_input()) { | ||||
| /* The switch has to be incorporated into the field. Both inputs have to be evaluated. */ | /* The switch has to be incorporated into the field. Both inputs have to be evaluated. */ | ||||
| const bool require_false = params.lazy_require_input(name_false); | const bool require_false = params.lazy_require_input(name_false); | ||||
| const bool require_true = params.lazy_require_input(name_true); | const bool require_true = params.lazy_require_input(name_true); | ||||
| if (require_false | require_true) { | if (require_false | require_true) { | ||||
| return; | return; | ||||
| } | } | ||||
| Field<T> falses_field = params.extract_input<Field<T>>(name_false); | Field<T> falses_field = params.extract_input<Field<T>>(name_false); | ||||
| Field<T> trues_field = params.extract_input<Field<T>>(name_true); | Field<T> trues_field = params.extract_input<Field<T>>(name_true); | ||||
| static fn::CustomMF_SI_SI_SI_SO<bool, T, T, T> switch_fn{ | static fn::CustomMF_SI_SI_SI_SO<bool, T, T, T> switch_fn{ | ||||
| "Switch", [](bool condition, const T &false_value, const T &true_value) { | "Switch", [](bool condition, const T &false_value, const T &true_value) { | ||||
| return condition ? true_value : false_value; | return condition ? true_value : false_value; | ||||
| }}; | }}; | ||||
| auto switch_op = std::make_shared<FieldOperation>(FieldOperation( | auto switch_op = std::make_shared<FieldOperation>(FieldOperation( | ||||
| std::move(switch_fn), | std::move(switch_fn), | ||||
| {std::move(switches_field), std::move(falses_field), std::move(trues_field)})); | {std::move(switches_field), std::move(falses_field), std::move(trues_field)})); | ||||
| params.set_output(name_output, Field<T>(switch_op, 0)); | params.set_output(attribute_math::default_name<T>(), Field<T>(switch_op, 0)); | ||||
| } | } | ||||
| else { | else { | ||||
| /* The switch input is constant, so just evaluate and forward one of the inputs. */ | /* The switch input is constant, so just evaluate and forward one of the inputs. */ | ||||
| const bool switch_value = fn::evaluate_constant_field(switches_field); | const bool switch_value = fn::evaluate_constant_field(switches_field); | ||||
| if (switch_value) { | if (switch_value) { | ||||
| params.set_input_unused(name_false); | params.set_input_unused(name_false); | ||||
| if (params.lazy_require_input(name_true)) { | if (params.lazy_require_input(name_true)) { | ||||
| return; | return; | ||||
| } | } | ||||
| params.set_output(name_output, params.extract_input<Field<T>>(name_true)); | params.set_output(attribute_math::default_name<T>(), | ||||
| params.extract_input<Field<T>>(name_true)); | |||||
| } | } | ||||
| else { | else { | ||||
| params.set_input_unused(name_true); | params.set_input_unused(name_true); | ||||
| if (params.lazy_require_input(name_false)) { | if (params.lazy_require_input(name_false)) { | ||||
| return; | return; | ||||
| } | } | ||||
| params.set_output(name_output, params.extract_input<Field<T>>(name_false)); | params.set_output(attribute_math::default_name<T>(), | ||||
| params.extract_input<Field<T>>(name_false)); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| template<typename T> void switch_no_fields(GeoNodeExecParams ¶ms, const StringRef suffix) | template<typename T> void switch_no_fields(GeoNodeExecParams ¶ms, const StringRef suffix) | ||||
| { | { | ||||
| if (params.lazy_require_input("Switch_001")) { | if (params.lazy_require_input("Switch_Single")) { | ||||
| return; | return; | ||||
| } | } | ||||
| bool switch_value = params.get_input<bool>("Switch_001"); | bool switch_value = params.get_input<bool>("Switch_Single"); | ||||
| const std::string name_false = "False" + suffix; | const std::string name_false = "False_" + suffix; | ||||
| const std::string name_true = "True" + suffix; | const std::string name_true = "True_" + suffix; | ||||
| const std::string name_output = "Output" + suffix; | |||||
| if (switch_value) { | if (switch_value) { | ||||
| params.set_input_unused(name_false); | params.set_input_unused(name_false); | ||||
| if (params.lazy_require_input(name_true)) { | if (params.lazy_require_input(name_true)) { | ||||
| return; | return; | ||||
| } | } | ||||
| params.set_output(name_output, params.extract_input<T>(name_true)); | params.set_output(suffix, params.extract_input<T>(name_true)); | ||||
| } | } | ||||
| else { | else { | ||||
| params.set_input_unused(name_true); | params.set_input_unused(name_true); | ||||
| if (params.lazy_require_input(name_false)) { | if (params.lazy_require_input(name_false)) { | ||||
| return; | return; | ||||
| } | } | ||||
| params.set_output(name_output, params.extract_input<T>(name_false)); | params.set_output(suffix, params.extract_input<T>(name_false)); | ||||
| } | } | ||||
| } | } | ||||
| static void node_geo_exec(GeoNodeExecParams params) | static void node_geo_exec(GeoNodeExecParams params) | ||||
| { | { | ||||
| const NodeSwitch &storage = node_storage(params.node()); | const NodeSwitch &storage = node_storage(params.node()); | ||||
| const eNodeSocketDatatype data_type = static_cast<eNodeSocketDatatype>(storage.input_type); | const eNodeSocketDatatype data_type = static_cast<eNodeSocketDatatype>(storage.input_type); | ||||
| switch (data_type) { | switch (data_type) { | ||||
| case SOCK_FLOAT: { | case SOCK_FLOAT: { | ||||
| switch_fields<float>(params, ""); | switch_fields<float>(params); | ||||
| break; | break; | ||||
| } | } | ||||
| case SOCK_INT: { | case SOCK_INT: { | ||||
| switch_fields<int>(params, "_001"); | switch_fields<int>(params); | ||||
| break; | break; | ||||
| } | } | ||||
| case SOCK_BOOLEAN: { | case SOCK_BOOLEAN: { | ||||
| switch_fields<bool>(params, "_002"); | switch_fields<bool>(params); | ||||
| break; | break; | ||||
| } | } | ||||
| case SOCK_VECTOR: { | case SOCK_VECTOR: { | ||||
| switch_fields<float3>(params, "_003"); | switch_fields<float3>(params); | ||||
| break; | break; | ||||
| } | } | ||||
| case SOCK_RGBA: { | case SOCK_RGBA: { | ||||
| switch_fields<ColorGeometry4f>(params, "_004"); | switch_fields<ColorGeometry4f>(params); | ||||
| break; | break; | ||||
| } | } | ||||
| case SOCK_STRING: { | case SOCK_STRING: { | ||||
| switch_fields<std::string>(params, "_005"); | switch_fields<std::string>(params); | ||||
| break; | break; | ||||
| } | } | ||||
| case SOCK_GEOMETRY: { | case SOCK_GEOMETRY: { | ||||
| switch_no_fields<GeometrySet>(params, "_006"); | switch_no_fields<GeometrySet>(params, "Geometry"); | ||||
| break; | break; | ||||
| } | } | ||||
| case SOCK_OBJECT: { | case SOCK_OBJECT: { | ||||
| switch_no_fields<Object *>(params, "_007"); | switch_no_fields<Object *>(params, "Object"); | ||||
| break; | break; | ||||
| } | } | ||||
| case SOCK_COLLECTION: { | case SOCK_COLLECTION: { | ||||
| switch_no_fields<Collection *>(params, "_008"); | switch_no_fields<Collection *>(params, "Collection"); | ||||
| break; | break; | ||||
| } | } | ||||
| case SOCK_TEXTURE: { | case SOCK_TEXTURE: { | ||||
| switch_no_fields<Tex *>(params, "_009"); | switch_no_fields<Tex *>(params, "Texture"); | ||||
| break; | break; | ||||
| } | } | ||||
| case SOCK_MATERIAL: { | case SOCK_MATERIAL: { | ||||
| switch_no_fields<Material *>(params, "_010"); | switch_no_fields<Material *>(params, "Material"); | ||||
| break; | break; | ||||
| } | } | ||||
| case SOCK_IMAGE: { | case SOCK_IMAGE: { | ||||
| switch_no_fields<Image *>(params, "_011"); | switch_no_fields<Image *>(params, "Image"); | ||||
| break; | break; | ||||
| } | } | ||||
| default: | default: | ||||
| BLI_assert_unreachable(); | BLI_assert_unreachable(); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| Show All 19 Lines | |||||