Connecting to some sockets of a few nodes via the drag link search would fail and trigger an assert, because the picked socket wasn't available. This was due to some sockets only being available with certain settings. This patch fixes these cases by adding the availability conditions of the socket to the node declaration with the `make_available` method or manually adding a `node_link_gather_search` function. Differential Revision: https://developer.blender.org/D14283
139 lines
5.0 KiB
C++
139 lines
5.0 KiB
C++
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#include "BLI_listbase.h"
|
|
#include "BLI_math_vector.h"
|
|
#include "BLI_string.h"
|
|
|
|
#include "RNA_enum_types.h"
|
|
|
|
#include "UI_interface.h"
|
|
#include "UI_resources.h"
|
|
|
|
#include "node_function_util.hh"
|
|
|
|
namespace blender::nodes::node_fn_rotate_euler_cc {
|
|
|
|
static void fn_node_rotate_euler_declare(NodeDeclarationBuilder &b)
|
|
{
|
|
auto enable_axis_angle = [](bNode &node) {
|
|
node.custom1 = FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE;
|
|
};
|
|
|
|
b.is_function_node();
|
|
b.add_input<decl::Vector>(N_("Rotation")).subtype(PROP_EULER).hide_value();
|
|
b.add_input<decl::Vector>(N_("Rotate By")).subtype(PROP_EULER).make_available([](bNode &node) {
|
|
node.custom1 = FN_NODE_ROTATE_EULER_TYPE_EULER;
|
|
});
|
|
b.add_input<decl::Vector>(N_("Axis"))
|
|
.default_value({0.0, 0.0, 1.0})
|
|
.subtype(PROP_XYZ)
|
|
.make_available(enable_axis_angle);
|
|
b.add_input<decl::Float>(N_("Angle")).subtype(PROP_ANGLE).make_available(enable_axis_angle);
|
|
b.add_output<decl::Vector>(N_("Rotation"));
|
|
}
|
|
|
|
static void fn_node_rotate_euler_update(bNodeTree *ntree, bNode *node)
|
|
{
|
|
bNodeSocket *rotate_by_socket = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 1));
|
|
bNodeSocket *axis_socket = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 2));
|
|
bNodeSocket *angle_socket = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 3));
|
|
|
|
nodeSetSocketAvailability(
|
|
ntree, rotate_by_socket, ELEM(node->custom1, FN_NODE_ROTATE_EULER_TYPE_EULER));
|
|
nodeSetSocketAvailability(
|
|
ntree, axis_socket, ELEM(node->custom1, FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE));
|
|
nodeSetSocketAvailability(
|
|
ntree, angle_socket, ELEM(node->custom1, FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE));
|
|
}
|
|
|
|
static void fn_node_rotate_euler_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
|
{
|
|
uiItemR(layout, ptr, "type", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
|
|
uiItemR(layout, ptr, "space", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
|
|
}
|
|
|
|
static const fn::MultiFunction *get_multi_function(bNode &bnode)
|
|
{
|
|
static fn::CustomMF_SI_SI_SO<float3, float3, float3> obj_euler_rot{
|
|
"Rotate Euler by Euler/Object", [](const float3 &input, const float3 &rotation) {
|
|
float input_mat[3][3];
|
|
eul_to_mat3(input_mat, input);
|
|
float rot_mat[3][3];
|
|
eul_to_mat3(rot_mat, rotation);
|
|
float mat_res[3][3];
|
|
mul_m3_m3m3(mat_res, rot_mat, input_mat);
|
|
float3 result;
|
|
mat3_to_eul(result, mat_res);
|
|
return result;
|
|
}};
|
|
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> obj_AA_rot{
|
|
"Rotate Euler by AxisAngle/Object",
|
|
[](const float3 &input, const float3 &axis, float angle) {
|
|
float input_mat[3][3];
|
|
eul_to_mat3(input_mat, input);
|
|
float rot_mat[3][3];
|
|
axis_angle_to_mat3(rot_mat, axis, angle);
|
|
float mat_res[3][3];
|
|
mul_m3_m3m3(mat_res, rot_mat, input_mat);
|
|
float3 result;
|
|
mat3_to_eul(result, mat_res);
|
|
return result;
|
|
}};
|
|
static fn::CustomMF_SI_SI_SO<float3, float3, float3> local_euler_rot{
|
|
"Rotate Euler by Euler/Local", [](const float3 &input, const float3 &rotation) {
|
|
float input_mat[3][3];
|
|
eul_to_mat3(input_mat, input);
|
|
float rot_mat[3][3];
|
|
eul_to_mat3(rot_mat, rotation);
|
|
float mat_res[3][3];
|
|
mul_m3_m3m3(mat_res, input_mat, rot_mat);
|
|
float3 result;
|
|
mat3_to_eul(result, mat_res);
|
|
return result;
|
|
}};
|
|
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> local_AA_rot{
|
|
"Rotate Euler by AxisAngle/Local", [](const float3 &input, const float3 &axis, float angle) {
|
|
float input_mat[3][3];
|
|
eul_to_mat3(input_mat, input);
|
|
float rot_mat[3][3];
|
|
axis_angle_to_mat3(rot_mat, axis, angle);
|
|
float mat_res[3][3];
|
|
mul_m3_m3m3(mat_res, input_mat, rot_mat);
|
|
float3 result;
|
|
mat3_to_eul(result, mat_res);
|
|
return result;
|
|
}};
|
|
short type = bnode.custom1;
|
|
short space = bnode.custom2;
|
|
if (type == FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE) {
|
|
return space == FN_NODE_ROTATE_EULER_SPACE_OBJECT ? &obj_AA_rot : &local_AA_rot;
|
|
}
|
|
if (type == FN_NODE_ROTATE_EULER_TYPE_EULER) {
|
|
return space == FN_NODE_ROTATE_EULER_SPACE_OBJECT ? &obj_euler_rot : &local_euler_rot;
|
|
}
|
|
BLI_assert_unreachable();
|
|
return nullptr;
|
|
}
|
|
|
|
static void fn_node_rotate_euler_build_multi_function(NodeMultiFunctionBuilder &builder)
|
|
{
|
|
const fn::MultiFunction *fn = get_multi_function(builder.node());
|
|
builder.set_matching_fn(fn);
|
|
}
|
|
|
|
} // namespace blender::nodes::node_fn_rotate_euler_cc
|
|
|
|
void register_node_type_fn_rotate_euler()
|
|
{
|
|
namespace file_ns = blender::nodes::node_fn_rotate_euler_cc;
|
|
|
|
static bNodeType ntype;
|
|
|
|
fn_node_type_base(&ntype, FN_NODE_ROTATE_EULER, "Rotate Euler", NODE_CLASS_CONVERTER);
|
|
ntype.declare = file_ns::fn_node_rotate_euler_declare;
|
|
ntype.draw_buttons = file_ns::fn_node_rotate_euler_layout;
|
|
node_type_update(&ntype, file_ns::fn_node_rotate_euler_update);
|
|
ntype.build_multi_function = file_ns::fn_node_rotate_euler_build_multi_function;
|
|
nodeRegisterType(&ntype);
|
|
}
|