Welcome to mirror list, hosted at ThFree Co, Russian Federation.

node_fn_rotate_euler.cc « nodes « function « nodes « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 813d0a265f74ae182fe1c0830e65550c843a92ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* 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 * /*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(const 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);
}