Geometry Nodes: Mix Rotations #109084
|
@ -10,6 +10,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "BLI_function_ref.hh"
|
||||||
#include "BLI_math.h"
|
#include "BLI_math.h"
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
mod_moder marked this conversation as resolved
Outdated
|
|||||||
|
|
||||||
|
@ -513,6 +514,14 @@ static const EnumPropertyItem rna_node_combsep_color_items[] = {
|
||||||
{0, nullptr, 0, nullptr, nullptr},
|
{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
|
#ifndef RNA_RUNTIME
|
||||||
static const EnumPropertyItem node_sampler_type_items[] = {
|
static const EnumPropertyItem node_sampler_type_items[] = {
|
||||||
{0, "NEAREST", 0, "Nearest", ""},
|
{0, "NEAREST", 0, "Nearest", ""},
|
||||||
|
@ -2062,7 +2071,7 @@ static StructRNA *rna_Node_register(Main *bmain,
|
||||||
|
|
||||||
static const EnumPropertyItem *itemf_function_check(
|
static const EnumPropertyItem *itemf_function_check(
|
||||||
const EnumPropertyItem *original_item_array,
|
const EnumPropertyItem *original_item_array,
|
||||||
bool (*value_supported)(const EnumPropertyItem *item))
|
blender::FunctionRef<bool(const EnumPropertyItem *item)> value_supported)
|
||||||
{
|
{
|
||||||
EnumPropertyItem *item_array = nullptr;
|
EnumPropertyItem *item_array = nullptr;
|
||||||
int items_len = 0;
|
int items_len = 0;
|
||||||
|
@ -3793,6 +3802,27 @@ static const EnumPropertyItem *renderresult_layers_add_enum(RenderLayer *rl)
|
||||||
return item;
|
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);
|
||||||
mod_moder marked this conversation as resolved
Outdated
Hans Goudey
commented
`[ptr]` -> `[&]`
|
|||||||
|
if (U.experimental.use_rotation_socket && data_type == SOCK_ROTATION) {
|
||||||
|
const bNodeTree *tree = reinterpret_cast<const bNodeTree *>(ptr->owner_id);
|
||||||
|
if (tree->type == NTREE_GEOMETRY) {
|
||||||
|
return true;
|
||||||
mod_moder marked this conversation as resolved
Hans Goudey
commented
This assert is unnecessary IMO, the pointer is de-referenced in the next line which shows it's not expected to be null. This assert is unnecessary IMO, the pointer is de-referenced in the next line which shows it's not expected to be null.
|
|||||||
|
}
|
||||||
|
}
|
||||||
|
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*/,
|
static const EnumPropertyItem *rna_Node_image_layer_itemf(bContext * /*C*/,
|
||||||
PointerRNA *ptr,
|
PointerRNA *ptr,
|
||||||
PropertyRNA * /*prop*/,
|
PropertyRNA * /*prop*/,
|
||||||
|
@ -5206,13 +5236,6 @@ static void def_compare(StructRNA *srna)
|
||||||
|
|
||||||
static void def_sh_mix(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[] = {
|
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_UNIFORM, "UNIFORM", 0, "Uniform", "Use a single factor for all components"},
|
||||||
{NODE_MIX_MODE_NON_UNIFORM, "NON_UNIFORM", 0, "Non-Uniform", "Per component factor"},
|
{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");
|
RNA_def_struct_sdna_from(srna, "NodeShaderMix", "storage");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE);
|
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_items(prop, rna_enum_mix_data_type_items);
|
||||||
RNA_def_property_enum_default(prop, SOCK_FLOAT);
|
RNA_def_property_enum_default(prop, SOCK_FLOAT);
|
||||||
RNA_def_property_ui_text(prop, "Data Type", "");
|
RNA_def_property_ui_text(prop, "Data Type", "");
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "BLI_math_quaternion.hh"
|
||||||
|
|
||||||
#include "UI_interface.h"
|
#include "UI_interface.h"
|
||||||
#include "UI_resources.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})
|
.default_value({0.5f, 0.5f, 0.5f, 1.0f})
|
||||||
.translation_context(BLT_I18NCONTEXT_ID_NODETREE);
|
.translation_context(BLT_I18NCONTEXT_ID_NODETREE);
|
||||||
|
|
||||||
|
b.add_input<decl::Rotation>("A", "A_Rotation")
|
||||||
|
.is_default_link_socket()
|
||||||
|
.translation_context(BLT_I18NCONTEXT_ID_NODETREE);
|
||||||
|
b.add_input<decl::Rotation>("B", "B_Rotation").translation_context(BLT_I18NCONTEXT_ID_NODETREE);
|
||||||
|
|
||||||
b.add_output<decl::Float>("Result", "Result_Float");
|
b.add_output<decl::Float>("Result", "Result_Float");
|
||||||
b.add_output<decl::Vector>("Result", "Result_Vector");
|
b.add_output<decl::Vector>("Result", "Result_Vector");
|
||||||
b.add_output<decl::Color>("Result", "Result_Color");
|
b.add_output<decl::Color>("Result", "Result_Color");
|
||||||
|
b.add_output<decl::Rotation>("Result", "Result_Rotation");
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sh_node_mix_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
static void sh_node_mix_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||||
{
|
{
|
||||||
const NodeShaderMix &data = node_storage(*static_cast<const bNode *>(ptr->data));
|
const NodeShaderMix &data = node_storage(*static_cast<const bNode *>(ptr->data));
|
||||||
uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
|
uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
|
||||||
if (data.data_type == SOCK_VECTOR) {
|
switch (data.data_type) {
|
||||||
uiItemR(layout, ptr, "factor_mode", 0, "", ICON_NONE);
|
case SOCK_FLOAT:
|
||||||
}
|
break;
|
||||||
if (data.data_type == SOCK_RGBA) {
|
case SOCK_VECTOR:
|
||||||
uiItemR(layout, ptr, "blend_type", 0, "", ICON_NONE);
|
uiItemR(layout, ptr, "factor_mode", 0, "", ICON_NONE);
|
||||||
uiItemR(layout, ptr, "clamp_result", 0, nullptr, ICON_NONE);
|
break;
|
||||||
uiItemR(layout, ptr, "clamp_factor", 0, nullptr, ICON_NONE);
|
case SOCK_RGBA:
|
||||||
}
|
uiItemR(layout, ptr, "blend_type", 0, "", ICON_NONE);
|
||||||
else {
|
uiItemR(layout, ptr, "clamp_result", 0, nullptr, ICON_NONE);
|
||||||
uiItemR(layout, ptr, "clamp_factor", 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*/,
|
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:
|
case SOCK_RGBA:
|
||||||
type = SOCK_RGBA;
|
type = SOCK_RGBA;
|
||||||
break;
|
break;
|
||||||
|
case SOCK_ROTATION:
|
||||||
|
type = SOCK_ROTATION;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -210,15 +226,21 @@ static void node_mix_gather_link_searches(GatherLinkSearchOpParams ¶ms)
|
||||||
weight);
|
weight);
|
||||||
weight--;
|
weight--;
|
||||||
}
|
}
|
||||||
params.add_item(
|
if (type != SOCK_ROTATION) {
|
||||||
IFACE_("Factor"),
|
params.add_item(
|
||||||
[type](LinkSearchOpParams ¶ms) {
|
IFACE_("Factor"),
|
||||||
bNode &node = params.add_node("ShaderNodeMix");
|
[type](LinkSearchOpParams ¶ms) {
|
||||||
node_storage(node).data_type = type;
|
bNode &node = params.add_node("ShaderNodeMix");
|
||||||
params.update_and_connect_available_socket(node, "Factor");
|
node_storage(node).data_type = type;
|
||||||
},
|
params.update_and_connect_available_socket(node, "Factor");
|
||||||
weight);
|
},
|
||||||
weight--;
|
weight);
|
||||||
|
weight--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == SOCK_ROTATION) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != SOCK_RGBA) {
|
if (type != SOCK_RGBA) {
|
||||||
|
@ -309,6 +331,8 @@ static const char *gpu_shader_get_name(eNodeSocketDatatype data_type,
|
||||||
BLI_assert_unreachable();
|
BLI_assert_unreachable();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
case SOCK_ROTATION:
|
||||||
|
return nullptr;
|
||||||
default:
|
default:
|
||||||
BLI_assert_unreachable();
|
BLI_assert_unreachable();
|
||||||
return nullptr;
|
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<float, math::Quaternion, math::Quaternion, math::Quaternion>(
|
||||||
|
"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<float, math::Quaternion, math::Quaternion, math::Quaternion>(
|
||||||
|
"Mix Rotation",
|
||||||
|
[](const float t, const math::Quaternion &a, const math::Quaternion &b) {
|
||||||
|
return math::interpolate(a, b, t);
|
||||||
|
});
|
||||||
|
return &fn;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
BLI_assert_unreachable();
|
BLI_assert_unreachable();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
Loading…
Reference in New Issue
Group this with the other BLI includes