Geometry Nodes: Matrix socket type, attribute type, and initial nodes #116166
|
@ -588,14 +588,13 @@ class NODE_MT_category_utilities_matrix(Menu):
|
|||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeTransformVector")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeTransformDirection")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeProjectVector")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeMatrixMultiply")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeLocationToTransform")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeRotationToTransform")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeScaleToTransform")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeCombineTransform")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeInvertMatrix")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeMatrixMultiply")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeProjectVector")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeSeparateTransform")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeTransformDirection")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeTransformVector")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeTransposeMatrix")
|
||||
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Matrix")
|
||||
|
||||
|
|
|
@ -1365,11 +1365,10 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
|
|||
#define FN_NODE_TRANSFORM_DIRECTION 1233
|
||||
#define FN_NODE_PROJECT_VECTOR 1234
|
||||
#define FN_NODE_MATRIX_MULTIPLY 1235
|
||||
#define FN_NODE_LOCATION_TO_TRANSFORM 1236
|
||||
#define FN_NODE_ROTATION_TO_TRANSFORM 1237
|
||||
#define FN_NODE_SCALE_TO_TRANSFORM 1238
|
||||
#define FN_NODE_INVERT_MATRIX 1239
|
||||
#define FN_NODE_TRANSPOSE_MATRIX 1240
|
||||
#define FN_NODE_COMBINE_TRANSFORM 1236
|
||||
#define FN_NODE_SEPARATE_TRANSFORM 1237
|
||||
#define FN_NODE_INVERT_MATRIX 1238
|
||||
#define FN_NODE_TRANSPOSE_MATRIX 1239
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -799,6 +799,7 @@ void BKE_mesh_eval_delete(Mesh *mesh_eval)
|
|||
|
||||
Mesh *BKE_mesh_copy_for_eval(const Mesh *source)
|
||||
{
|
||||
BLI_assert(source != nullptr);
|
||||
return reinterpret_cast<Mesh *>(
|
||||
BKE_id_copy_ex(nullptr, &source->id, nullptr, LIB_ID_COPY_LOCALIZE));
|
||||
}
|
||||
|
|
|
@ -45,8 +45,7 @@ static void add_values_to_text_cache(const GVArray &values,
|
|||
const T &value = values_typed[i];
|
||||
|
||||
char numstr[32];
|
||||
size_t numstr_len;
|
||||
|
||||
size_t numstr_len = 0;
|
||||
if constexpr (std::is_same_v<T, bool>) {
|
||||
numstr_len = SNPRINTF_RLEN(numstr, "%s", value ? "True" : "False");
|
||||
}
|
||||
|
|
|
@ -266,6 +266,7 @@ DefNode(FunctionNode, FN_NODE_ALIGN_EULER_TO_VECTOR, 0, "ALIGN_EULER_TO_VECTOR",
|
|||
DefNode(FunctionNode, FN_NODE_AXIS_ANGLE_TO_ROTATION, 0, "AXIS_ANGLE_TO_ROTATION", AxisAngleToRotation, "Axis Angle to Rotation", "")
|
||||
DefNode(FunctionNode, FN_NODE_BOOLEAN_MATH, 0, "BOOLEAN_MATH", BooleanMath, "Boolean Math", "")
|
||||
DefNode(FunctionNode, FN_NODE_COMBINE_COLOR, 0, "COMBINE_COLOR", CombineColor, "Combine Color", "")
|
||||
DefNode(FunctionNode, FN_NODE_QUATERNION_TO_ROTATION, 0, "QUATERNION_TO_ROTATION", QuaternionToRotation, "Quaternion to Rotation", "")
|
||||
DefNode(FunctionNode, FN_NODE_COMPARE, 0, "COMPARE", Compare, "Compare", "")
|
||||
DefNode(FunctionNode, FN_NODE_EULER_TO_ROTATION, 0, "EULER_TO_ROTATION", EulerToRotation, "Euler to Rotation", "")
|
||||
DefNode(FunctionNode, FN_NODE_FLOAT_TO_INT, def_float_to_int, "FLOAT_TO_INT", FloatToInt, "Float to Integer", "")
|
||||
|
@ -277,20 +278,18 @@ DefNode(FunctionNode, FN_NODE_INPUT_STRING, def_fn_input_string, "INPUT_STRING",
|
|||
DefNode(FunctionNode, FN_NODE_INPUT_VECTOR, def_fn_input_vector, "INPUT_VECTOR", InputVector, "Vector", "")
|
||||
DefNode(FunctionNode, FN_NODE_INVERT_MATRIX, 0, "INVERT_MATRIX", InvertMatrix, "Invert Matrix", "")
|
||||
DefNode(FunctionNode, FN_NODE_INVERT_ROTATION, 0, "INVERT_ROTATION", InvertRotation, "Invert Rotation", "")
|
||||
DefNode(FunctionNode, FN_NODE_LOCATION_TO_TRANSFORM, 0, "LOCATION_TO_TRANSFORM", LocationToTransform, "Location to Transform", "")
|
||||
DefNode(FunctionNode, FN_NODE_COMBINE_TRANSFORM, 0, "COMBINE_TRANSFORM", CombineTransform, "Combine Transform", "")
|
||||
DefNode(FunctionNode, FN_NODE_MATRIX_MULTIPLY, 0, "MATRIX_MULTIPLY", MatrixMultiply, "Matrix Multiply", "")
|
||||
DefNode(FunctionNode, FN_NODE_PROJECT_VECTOR, 0, "PROJECT_VECTOR", ProjectVector, "Project Vector", "")
|
||||
DefNode(FunctionNode, FN_NODE_QUATERNION_TO_ROTATION, 0, "QUATERNION_TO_ROTATION", QuaternionToRotation, "Quaternion to Rotation", "")
|
||||
DefNode(FunctionNode, FN_NODE_RANDOM_VALUE, def_fn_random_value, "RANDOM_VALUE", RandomValue, "Random Value", "")
|
||||
DefNode(FunctionNode, FN_NODE_REPLACE_STRING, 0, "REPLACE_STRING", ReplaceString, "Replace String", "")
|
||||
DefNode(FunctionNode, FN_NODE_ROTATE_EULER, def_fn_rotate_euler, "ROTATE_EULER", RotateEuler, "Rotate Euler", "")
|
||||
DefNode(FunctionNode, FN_NODE_ROTATE_VECTOR, 0, "ROTATE_VECTOR", RotateVector, "Rotate Vector", "")
|
||||
DefNode(FunctionNode, FN_NODE_ROTATION_TO_AXIS_ANGLE, 0, "ROTATION_TO_AXIS_ANGLE", RotationToAxisAngle, "Rotation to Axis Angle", "")
|
||||
DefNode(FunctionNode, FN_NODE_ROTATION_TO_EULER, 0, "ROTATION_TO_EULER", RotationToEuler, "Rotation to Euler", "")
|
||||
DefNode(FunctionNode, FN_NODE_ROTATION_TO_QUATERNION, 0, "ROTATION_TO_QUATERNION", RotationToQuaternion, "Rotation to Quaternion", "")
|
||||
DefNode(FunctionNode, FN_NODE_ROTATION_TO_TRANSFORM, 0, "ROTATION_TO_TRANSFORM", RotationToTransform, "Rotation to Transform", "")
|
||||
DefNode(FunctionNode, FN_NODE_SCALE_TO_TRANSFORM, 0, "SCALE_TO_TRANSFORM", ScaleToTransform, "Scale to Transform", "")
|
||||
DefNode(FunctionNode, FN_NODE_SEPARATE_COLOR, 0, "SEPARATE_COLOR", SeparateColor, "Separate Color", "")
|
||||
DefNode(FunctionNode, FN_NODE_SEPARATE_TRANSFORM, 0, "SEPARATE_TRANSFORM", SeparateTransform, "Separate Transform", "")
|
||||
DefNode(FunctionNode, FN_NODE_ROTATION_TO_QUATERNION, 0, "ROTATION_TO_QUATERNION", RotationToQuaternion, "Rotation to Quaternion", "")
|
||||
DefNode(FunctionNode, FN_NODE_SLICE_STRING, 0, "SLICE_STRING", SliceString, "Slice String", "")
|
||||
DefNode(FunctionNode, FN_NODE_STRING_LENGTH, 0, "STRING_LENGTH", StringLength, "String Length", "")
|
||||
DefNode(FunctionNode, FN_NODE_TRANSFORM_DIRECTION, 0, "TRANSFORM_DIRECTION", TransformDirection, "Transform Direction", "")
|
||||
HooglyBoogly marked this conversation as resolved
Outdated
|
||||
|
|
|
@ -33,7 +33,7 @@ set(SRC
|
|||
nodes/node_fn_input_vector.cc
|
||||
nodes/node_fn_invert_matrix.cc
|
||||
nodes/node_fn_invert_rotation.cc
|
||||
nodes/node_fn_location_to_transform.cc
|
||||
nodes/node_fn_combine_transform.cc
|
||||
nodes/node_fn_matrix_multiply.cc
|
||||
nodes/node_fn_project_vector.cc
|
||||
nodes/node_fn_quaternion_to_rotation.cc
|
||||
|
@ -44,9 +44,8 @@ set(SRC
|
|||
nodes/node_fn_rotation_to_axis_angle.cc
|
||||
nodes/node_fn_rotation_to_euler.cc
|
||||
nodes/node_fn_rotation_to_quaternion.cc
|
||||
nodes/node_fn_rotation_to_transform.cc
|
||||
nodes/node_fn_scale_to_transform.cc
|
||||
nodes/node_fn_separate_color.cc
|
||||
nodes/node_fn_separate_transform.cc
|
||||
nodes/node_fn_slice_string.cc
|
||||
nodes/node_fn_string_length.cc
|
||||
nodes/node_fn_transform_direction.cc
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
#include "BLI_math_rotation.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_combine_transform_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Vector>("Location").subtype(PROP_TRANSLATION);
|
||||
b.add_input<decl::Rotation>("Rotation");
|
||||
b.add_input<decl::Vector>("Scale").default_value(float3(1)).subtype(PROP_XYZ);
|
||||
b.add_output<decl::Matrix>("Transform");
|
||||
};
|
||||
|
||||
class CombineTransformFunction : public mf::MultiFunction {
|
||||
public:
|
||||
CombineTransformFunction()
|
||||
{
|
||||
static const mf::Signature signature = []() {
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Combine Transform", signature};
|
||||
builder.single_input<float3>("Location");
|
||||
builder.single_input<math::Quaternion>("Rotation");
|
||||
builder.single_input<float3>("Scale");
|
||||
builder.single_output<float4x4>("Transform");
|
||||
return signature;
|
||||
}();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
|
||||
{
|
||||
const VArray location = params.readonly_single_input<float3>(0, "Location");
|
||||
const VArray rotation = params.readonly_single_input<math::Quaternion>(1, "Rotation");
|
||||
const VArray scale = params.readonly_single_input<float3>(2, "Scale");
|
||||
MutableSpan transforms = params.uninitialized_single_output<float4x4>(3, "Transform");
|
||||
|
||||
const std::optional<float3> location_single = location.get_if_single();
|
||||
const std::optional<math::Quaternion> rotation_single = rotation.get_if_single();
|
||||
const std::optional<float3> scale_single = scale.get_if_single();
|
||||
|
||||
const bool no_translation = location_single && math::is_zero(*location_single);
|
||||
const bool no_rotation = rotation_single && math::angle_of(*rotation_single).radian() < 1e-7f;
|
||||
const bool no_scale = scale_single && math::is_equal(*scale_single, float3(1), 1e-7f);
|
||||
|
||||
if (no_rotation && no_scale) {
|
||||
mask.foreach_index(
|
||||
[&](const int64_t i) { transforms[i] = math::from_location<float4x4>(location[i]); });
|
||||
}
|
||||
else if (no_translation && no_scale) {
|
||||
mask.foreach_index(
|
||||
[&](const int64_t i) { transforms[i] = math::from_rotation<float4x4>(rotation[i]); });
|
||||
}
|
||||
else if (no_translation && no_rotation) {
|
||||
mask.foreach_index(
|
||||
[&](const int64_t i) { transforms[i] = math::from_scale<float4x4>(scale[i]); });
|
||||
}
|
||||
Iliya Katushenock
commented
I hope will find time for the benchmarks for the last loop to check if `mask.foreach_index` -> `mask.foreach_index_optimized<int>`.
`const int64_t i` -> `const int i`.
Same in other nodes.
I hope will find time for the benchmarks for the last loop to check if `devirtualize_varray` and `foreach_index_optimized` makes sense too, then this will be in main.
Hans Goudey
commented
Unless I can prove it's faster I don't think this is worth it. Unless I can prove it's faster I don't think this is worth it.
|
||||
else {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
transforms[i] = math::from_loc_rot_scale<float4x4>(location[i], rotation[i], scale[i]);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static CombineTransformFunction fn;
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(&ntype, FN_NODE_COMBINE_TRANSFORM, "Combine Transform", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_combine_transform_cc
|
|
@ -1,37 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_location_to_transform_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Vector>("Location").subtype(PROP_TRANSLATION);
|
||||
b.add_output<decl::Matrix>("Transform");
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI1_SO<float3, float4x4>(
|
||||
"Location to Transform",
|
||||
[](float3 location) { return math::from_location<float4x4>(location); });
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(
|
||||
&ntype, FN_NODE_LOCATION_TO_TRANSFORM, "Location to Transform", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_location_to_transform_cc
|
|
@ -1,37 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_rotation_to_transform_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Rotation>("Rotation");
|
||||
b.add_output<decl::Matrix>("Transform");
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI1_SO<math::Quaternion, float4x4>(
|
||||
"Rotation to Transform",
|
||||
[](math::Quaternion quat) { return math::from_rotation<float4x4>(quat); });
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(
|
||||
&ntype, FN_NODE_ROTATION_TO_TRANSFORM, "Rotation to Transform", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_rotation_to_transform_cc
|
|
@ -1,36 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_scale_to_transform_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Vector>("Scale").subtype(PROP_XYZ);
|
||||
b.add_output<decl::Matrix>("Transform");
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI1_SO<float3, float4x4>(
|
||||
"Scale to Transform", [](float3 scale) { return math::from_scale<float4x4>(scale); });
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(
|
||||
&ntype, FN_NODE_SCALE_TO_TRANSFORM, "Scale to Transform", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_scale_to_transform_cc
|
|
@ -0,0 +1,82 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
#include "BLI_math_rotation.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_separate_transform_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Matrix>("Transform");
|
||||
b.add_output<decl::Vector>("Location").subtype(PROP_TRANSLATION);
|
||||
b.add_output<decl::Rotation>("Rotation");
|
||||
b.add_output<decl::Vector>("Scale").subtype(PROP_XYZ);
|
||||
};
|
||||
|
||||
class SeparateTransformFunction : public mf::MultiFunction {
|
||||
public:
|
||||
SeparateTransformFunction()
|
||||
{
|
||||
static const mf::Signature signature = []() {
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Separate Transform", signature};
|
||||
builder.single_input<float4x4>("Transform");
|
||||
builder.single_output<float3>("Location", mf::ParamFlag::SupportsUnusedOutput);
|
||||
builder.single_output<math::Quaternion>("Rotation", mf::ParamFlag::SupportsUnusedOutput);
|
||||
builder.single_output<float3>("Scale", mf::ParamFlag::SupportsUnusedOutput);
|
||||
return signature;
|
||||
}();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
|
||||
{
|
||||
const VArraySpan transforms = params.readonly_single_input<float4x4>(0, "Transform");
|
||||
MutableSpan location = params.uninitialized_single_output_if_required<float3>(1, "Location");
|
||||
MutableSpan rotation = params.uninitialized_single_output_if_required<math::Quaternion>(
|
||||
2, "Rotation");
|
||||
MutableSpan scale = params.uninitialized_single_output_if_required<float3>(3, "Scale");
|
||||
|
||||
if (!location.is_empty()) {
|
||||
mask.foreach_index_optimized<int64_t>(
|
||||
[&](const int64_t i) { location[i] = transforms[i].location(); });
|
||||
}
|
||||
|
||||
if (rotation.is_empty() && !scale.is_empty()) {
|
||||
mask.foreach_index([&](const int64_t i) { location[i] = math::to_scale(transforms[i]); });
|
||||
}
|
||||
else if (!rotation.is_empty() && scale.is_empty()) {
|
||||
mask.foreach_index(
|
||||
[&](const int64_t i) { rotation[i] = math::to_quaternion(transforms[i]); });
|
||||
}
|
||||
else if (!rotation.is_empty() && !scale.is_empty()) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
math::to_rot_scale(float3x3(transforms[i]), rotation[i], scale[i]);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static SeparateTransformFunction fn;
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(
|
||||
&ntype, FN_NODE_SEPARATE_TRANSFORM, "Separate Transform", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_separate_transform_cc
|
Loading…
Reference in New Issue
Some missing renames.