diff --git a/source/blender/makesrna/intern/rna_nodetree.cc b/source/blender/makesrna/intern/rna_nodetree.cc index 6f8412e9947..158bd606c38 100644 --- a/source/blender/makesrna/intern/rna_nodetree.cc +++ b/source/blender/makesrna/intern/rna_nodetree.cc @@ -10,6 +10,7 @@ #include #include +#include "BLI_function_ref.hh" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -513,6 +514,14 @@ static const EnumPropertyItem rna_node_combsep_color_items[] = { {0, nullptr, 0, nullptr, nullptr}, }; +static const EnumPropertyItem rna_enum_mix_data_type_items[] = { + {SOCK_FLOAT, "FLOAT", 0, "Float", ""}, + {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, + {SOCK_RGBA, "RGBA", 0, "Color", ""}, + {SOCK_ROTATION, "ROTATION", 0, "Rotation", ""}, + {0, nullptr, 0, nullptr, nullptr}, +}; + #ifndef RNA_RUNTIME static const EnumPropertyItem node_sampler_type_items[] = { {0, "NEAREST", 0, "Nearest", ""}, @@ -2062,7 +2071,7 @@ static StructRNA *rna_Node_register(Main *bmain, static const EnumPropertyItem *itemf_function_check( const EnumPropertyItem *original_item_array, - bool (*value_supported)(const EnumPropertyItem *item)) + blender::FunctionRef value_supported) { EnumPropertyItem *item_array = nullptr; int items_len = 0; @@ -3793,6 +3802,27 @@ static const EnumPropertyItem *renderresult_layers_add_enum(RenderLayer *rl) return item; } +static const EnumPropertyItem *rna_ShaderNodeMix_data_type_itemf(bContext * /*C*/, + PointerRNA *ptr, + PropertyRNA * /*prop*/, + bool *r_free) +{ + *r_free = true; + + const auto rotation_supported_mix = [&](const EnumPropertyItem *item) -> bool { + const eNodeSocketDatatype data_type = eNodeSocketDatatype(item->value); + if (U.experimental.use_rotation_socket && data_type == SOCK_ROTATION) { + const bNodeTree *tree = reinterpret_cast(ptr->owner_id); + if (tree->type == NTREE_GEOMETRY) { + return true; + } + } + return ELEM(data_type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA); + }; + + return itemf_function_check(rna_enum_mix_data_type_items, rotation_supported_mix); +} + static const EnumPropertyItem *rna_Node_image_layer_itemf(bContext * /*C*/, PointerRNA *ptr, PropertyRNA * /*prop*/, @@ -5206,13 +5236,6 @@ static void def_compare(StructRNA *srna) static void def_sh_mix(StructRNA *srna) { - static const EnumPropertyItem rna_enum_mix_data_type_items[] = { - {SOCK_FLOAT, "FLOAT", 0, "Float", ""}, - {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, - {SOCK_RGBA, "RGBA", 0, "Color", ""}, - {0, nullptr, 0, nullptr, nullptr}, - }; - static const EnumPropertyItem rna_enum_mix_mode_items[] = { {NODE_MIX_MODE_UNIFORM, "UNIFORM", 0, "Uniform", "Use a single factor for all components"}, {NODE_MIX_MODE_NON_UNIFORM, "NON_UNIFORM", 0, "Non-Uniform", "Per component factor"}, @@ -5224,6 +5247,7 @@ static void def_sh_mix(StructRNA *srna) RNA_def_struct_sdna_from(srna, "NodeShaderMix", "storage"); prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_funcs(prop, nullptr, nullptr, "rna_ShaderNodeMix_data_type_itemf"); RNA_def_property_enum_items(prop, rna_enum_mix_data_type_items); RNA_def_property_enum_default(prop, SOCK_FLOAT); RNA_def_property_ui_text(prop, "Data Type", ""); diff --git a/source/blender/nodes/shader/nodes/node_shader_mix.cc b/source/blender/nodes/shader/nodes/node_shader_mix.cc index 42f23d8ecbd..70cf6a2d940 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mix.cc +++ b/source/blender/nodes/shader/nodes/node_shader_mix.cc @@ -8,6 +8,8 @@ #include +#include "BLI_math_quaternion.hh" + #include "UI_interface.h" #include "UI_resources.h" @@ -62,26 +64,37 @@ static void sh_node_mix_declare(NodeDeclarationBuilder &b) .default_value({0.5f, 0.5f, 0.5f, 1.0f}) .translation_context(BLT_I18NCONTEXT_ID_NODETREE); + b.add_input("A", "A_Rotation") + .is_default_link_socket() + .translation_context(BLT_I18NCONTEXT_ID_NODETREE); + b.add_input("B", "B_Rotation").translation_context(BLT_I18NCONTEXT_ID_NODETREE); + b.add_output("Result", "Result_Float"); b.add_output("Result", "Result_Vector"); b.add_output("Result", "Result_Color"); + b.add_output("Result", "Result_Rotation"); }; static void sh_node_mix_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) { const NodeShaderMix &data = node_storage(*static_cast(ptr->data)); uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); - if (data.data_type == SOCK_VECTOR) { - uiItemR(layout, ptr, "factor_mode", 0, "", ICON_NONE); - } - if (data.data_type == SOCK_RGBA) { - uiItemR(layout, ptr, "blend_type", 0, "", ICON_NONE); - uiItemR(layout, ptr, "clamp_result", 0, nullptr, ICON_NONE); - uiItemR(layout, ptr, "clamp_factor", 0, nullptr, ICON_NONE); - } - else { - uiItemR(layout, ptr, "clamp_factor", 0, nullptr, ICON_NONE); + switch (data.data_type) { + case SOCK_FLOAT: + break; + case SOCK_VECTOR: + uiItemR(layout, ptr, "factor_mode", 0, "", ICON_NONE); + break; + case SOCK_RGBA: + uiItemR(layout, ptr, "blend_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "clamp_result", 0, nullptr, ICON_NONE); + break; + case SOCK_ROTATION: + break; + default: + BLI_assert_unreachable(); } + uiItemR(layout, ptr, "clamp_factor", 0, nullptr, ICON_NONE); } static void sh_node_mix_label(const bNodeTree * /*ntree*/, @@ -167,6 +180,9 @@ static void node_mix_gather_link_searches(GatherLinkSearchOpParams ¶ms) case SOCK_RGBA: type = SOCK_RGBA; break; + case SOCK_ROTATION: + type = SOCK_ROTATION; + break; default: return; } @@ -210,15 +226,21 @@ static void node_mix_gather_link_searches(GatherLinkSearchOpParams ¶ms) weight); weight--; } - params.add_item( - IFACE_("Factor"), - [type](LinkSearchOpParams ¶ms) { - bNode &node = params.add_node("ShaderNodeMix"); - node_storage(node).data_type = type; - params.update_and_connect_available_socket(node, "Factor"); - }, - weight); - weight--; + if (type != SOCK_ROTATION) { + params.add_item( + IFACE_("Factor"), + [type](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("ShaderNodeMix"); + node_storage(node).data_type = type; + params.update_and_connect_available_socket(node, "Factor"); + }, + weight); + weight--; + } + } + + if (type == SOCK_ROTATION) { + return; } if (type != SOCK_RGBA) { @@ -309,6 +331,8 @@ static const char *gpu_shader_get_name(eNodeSocketDatatype data_type, BLI_assert_unreachable(); return nullptr; } + case SOCK_ROTATION: + return nullptr; default: BLI_assert_unreachable(); return nullptr; @@ -480,6 +504,26 @@ static const mf::MultiFunction *get_multi_function(const bNode &node) } } } + case SOCK_ROTATION: { + if (clamp_factor) { + static auto fn = + mf::build::SI3_SO( + "Clamp Mix Rotation", + [](const float t, const math::Quaternion &a, const math::Quaternion &b) { + return math::interpolate(a, b, math::clamp(t, 0.0f, 1.0f)); + }); + return &fn; + } + else { + static auto fn = + mf::build::SI3_SO( + "Mix Rotation", + [](const float t, const math::Quaternion &a, const math::Quaternion &b) { + return math::interpolate(a, b, t); + }); + return &fn; + } + } } BLI_assert_unreachable(); return nullptr;