Blender V5.0
node_fn_rotate_euler.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_listbase.h"
6#include "BLI_math_matrix.h"
7#include "BLI_math_rotation.h"
8
9#include "RNA_enum_types.hh"
10
12#include "UI_resources.hh"
13
14#include "node_function_util.hh"
15
17
19{
20 auto enable_axis_angle = [](bNode &node) {
22 };
23
24 b.is_function_node();
25 b.add_input<decl::Vector>("Rotation").subtype(PROP_EULER).hide_value();
26 b.add_input<decl::Vector>("Rotate By").subtype(PROP_EULER).make_available([](bNode &node) {
28 });
29 b.add_input<decl::Vector>("Axis")
30 .default_value({0.0, 0.0, 1.0})
31 .subtype(PROP_XYZ)
32 .make_available(enable_axis_angle);
33 b.add_input<decl::Float>("Angle").subtype(PROP_ANGLE).make_available(enable_axis_angle);
34 b.add_output<decl::Vector>("Rotation");
35}
36
37static void node_update(bNodeTree *ntree, bNode *node)
38{
39 bNodeSocket *rotate_by_socket = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 1));
40 bNodeSocket *axis_socket = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 2));
41 bNodeSocket *angle_socket = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 3));
42
44 *ntree, *rotate_by_socket, ELEM(node->custom1, FN_NODE_ROTATE_EULER_TYPE_EULER));
46 *ntree, *axis_socket, ELEM(node->custom1, FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE));
48 *ntree, *angle_socket, ELEM(node->custom1, FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE));
49}
50
51static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
52{
53 layout->prop(ptr, "rotation_type", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
54 layout->prop(ptr, "space", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
55}
56
57static const mf::MultiFunction *get_multi_function(const bNode &bnode)
58{
59 static auto obj_euler_rot = mf::build::SI2_SO<float3, float3, float3>(
60 "Rotate Euler by Euler/Object", [](const float3 &input, const float3 &rotation) {
61 float input_mat[3][3];
62 eul_to_mat3(input_mat, input);
63 float rot_mat[3][3];
64 eul_to_mat3(rot_mat, rotation);
65 float mat_res[3][3];
66 mul_m3_m3m3(mat_res, rot_mat, input_mat);
68 mat3_to_eul(result, mat_res);
69 return result;
70 });
71 static auto obj_AA_rot = mf::build::SI3_SO<float3, float3, float, float3>(
72 "Rotate Euler by AxisAngle/Object",
73 [](const float3 &input, const float3 &axis, float angle) {
74 float input_mat[3][3];
75 eul_to_mat3(input_mat, input);
76 float rot_mat[3][3];
77 axis_angle_to_mat3(rot_mat, axis, angle);
78 float mat_res[3][3];
79 mul_m3_m3m3(mat_res, rot_mat, input_mat);
81 mat3_to_eul(result, mat_res);
82 return result;
83 });
84 static auto local_euler_rot = mf::build::SI2_SO<float3, float3, float3>(
85 "Rotate Euler by Euler/Local", [](const float3 &input, const float3 &rotation) {
86 float input_mat[3][3];
87 eul_to_mat3(input_mat, input);
88 float rot_mat[3][3];
89 eul_to_mat3(rot_mat, rotation);
90 float mat_res[3][3];
91 mul_m3_m3m3(mat_res, input_mat, rot_mat);
93 mat3_to_eul(result, mat_res);
94 return result;
95 });
96 static auto local_AA_rot = mf::build::SI3_SO<float3, float3, float, float3>(
97 "Rotate Euler by AxisAngle/Local", [](const float3 &input, const float3 &axis, float angle) {
98 float input_mat[3][3];
99 eul_to_mat3(input_mat, input);
100 float rot_mat[3][3];
101 axis_angle_to_mat3(rot_mat, axis, angle);
102 float mat_res[3][3];
103 mul_m3_m3m3(mat_res, input_mat, rot_mat);
105 mat3_to_eul(result, mat_res);
106 return result;
107 });
108 short type = bnode.custom1;
109 short space = bnode.custom2;
111 return space == FN_NODE_ROTATE_EULER_SPACE_OBJECT ?
112 static_cast<const mf::MultiFunction *>(&obj_AA_rot) :
113 &local_AA_rot;
114 }
116 return space == FN_NODE_ROTATE_EULER_SPACE_OBJECT ?
117 static_cast<const mf::MultiFunction *>(&obj_euler_rot) :
118 &local_euler_rot;
119 }
121 return nullptr;
122}
123
125{
126 const mf::MultiFunction *fn = get_multi_function(builder.node());
127 builder.set_matching_fn(fn);
128}
129
130static void node_register()
131{
132 static blender::bke::bNodeType ntype;
133
134 fn_node_type_base(&ntype, "FunctionNodeRotateEuler", FN_NODE_ROTATE_EULER);
135 ntype.ui_name = "Rotate Euler";
136 ntype.ui_description = "Apply a secondary Euler rotation to a given Euler rotation";
137 ntype.enum_name_legacy = "ROTATE_EULER";
139 ntype.declare = node_declare;
141 ntype.updatefunc = node_update;
143 ntype.deprecation_notice = N_("Use the \"Rotate Rotation\" node instead");
145}
147
148} // namespace blender::nodes::node_fn_rotate_euler_cc
#define NODE_CLASS_CONVERTER
Definition BKE_node.hh:453
#define FN_NODE_ROTATE_EULER
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
void eul_to_mat3(float mat[3][3], const float eul[3])
void mat3_to_eul(float eul[3], const float mat[3][3])
void axis_angle_to_mat3(float R[3][3], const float axis[3], float angle)
#define ELEM(...)
@ FN_NODE_ROTATE_EULER_TYPE_EULER
@ FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE
@ FN_NODE_ROTATE_EULER_SPACE_OBJECT
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
#define NOD_REGISTER_NODE(REGISTER_FUNC)
@ PROP_XYZ
Definition RNA_types.hh:269
@ PROP_ANGLE
Definition RNA_types.hh:252
@ PROP_EULER
Definition RNA_types.hh:266
@ UI_ITEM_R_EXPAND
void set_matching_fn(const mf::MultiFunction *fn)
void make_available(bNode &node) const
#define input
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
void node_set_socket_availability(bNodeTree &ntree, bNodeSocket &sock, bool is_available)
Definition node.cc:4739
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
static const mf::MultiFunction * get_multi_function(const bNode &bnode)
static void node_update(bNodeTree *ntree, bNode *node)
static void node_declare(NodeDeclarationBuilder &b)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
VecBase< float, 3 > float3
void fn_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
int16_t custom1
ListBase inputs
int16_t custom2
Defines a node type.
Definition BKE_node.hh:238
std::string ui_description
Definition BKE_node.hh:244
NodeMultiFunctionBuildFunction build_multi_function
Definition BKE_node.hh:351
const char * deprecation_notice
Definition BKE_node.hh:424
const char * enum_name_legacy
Definition BKE_node.hh:247
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:259
NodeDeclareFunction declare
Definition BKE_node.hh:362
void(* updatefunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:281
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4238