Matrix operations and sockets for geometry nodes #105408
|
@ -246,6 +246,7 @@ class NODE_MT_geometry_node_GEO_INPUT_CONSTANT(Menu):
|
|||
node_add_menu.add_node_type(layout, "GeometryNodeInputImage")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeInputInt")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMaterial")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeInputMatrix")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeInputString")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeValue")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeInputVector")
|
||||
|
@ -504,6 +505,7 @@ class NODE_MT_category_GEO_UTILITIES(Menu):
|
|||
layout.separator()
|
||||
layout.menu("NODE_MT_category_GEO_UTILITIES_FIELD")
|
||||
layout.menu("NODE_MT_category_GEO_UTILITIES_MATH")
|
||||
layout.menu("NODE_MT_category_GEO_UTILITIES_MATRIX")
|
||||
layout.menu("NODE_MT_category_GEO_UTILITIES_ROTATION")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeRandomValue")
|
||||
|
@ -551,6 +553,23 @@ class NODE_MT_category_GEO_UTILITIES_MATH(Menu):
|
|||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
class NODE_MT_category_GEO_UTILITIES_MATRIX(Menu):
|
||||
bl_idname = "NODE_MT_category_GEO_UTILITIES_MATRIX"
|
||||
bl_label = "Matrix"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeCombineMatrix")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeSeparateMatrix")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeDecomposeMatrix")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeMatrixMath")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeMatrixTransform")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeRotateMatrix")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeScaleMatrix")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeTranslateMatrix")
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
class NODE_MT_category_GEO_UV(Menu):
|
||||
bl_idname = "NODE_MT_category_GEO_UV"
|
||||
bl_label = "UV"
|
||||
|
@ -679,6 +698,7 @@ classes = (
|
|||
NODE_MT_category_GEO_VECTOR,
|
||||
NODE_MT_category_GEO_UTILITIES_FIELD,
|
||||
NODE_MT_category_GEO_UTILITIES_MATH,
|
||||
NODE_MT_category_GEO_UTILITIES_MATRIX,
|
||||
NODE_MT_category_GEO_UTILITIES_ROTATION,
|
||||
NODE_MT_category_GEO_GROUP,
|
||||
NODE_MT_category_GEO_LAYOUT,
|
||||
|
|
|
@ -1575,6 +1575,15 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
|
|||
#define FN_NODE_INPUT_INT 1220
|
||||
#define FN_NODE_SEPARATE_COLOR 1221
|
||||
#define FN_NODE_COMBINE_COLOR 1222
|
||||
#define FN_NODE_INPUT_MATRIX 1224
|
||||
#define FN_NODE_SEPARATE_MATRIX 1225
|
||||
#define FN_NODE_COMBINE_MATRIX 1226
|
||||
#define FN_NODE_MATRIX_MATH 1227
|
||||
#define FN_NODE_DECOMPOSE_MATRIX 1228
|
||||
#define FN_NODE_ROTATE_MATRIX 1229
|
||||
#define FN_NODE_SCALE_MATRIX 1230
|
||||
#define FN_NODE_TRANSLATE_MATRIX 1231
|
||||
#define FN_NODE_MATRIX_TRANSFORM 1232
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -94,6 +94,10 @@ static int attribute_data_type_complexity(const eCustomDataType data_type)
|
|||
return 6;
|
||||
case CD_PROP_COLOR:
|
||||
return 7;
|
||||
case CD_PROP_FLOAT3X3:
|
||||
return 8;
|
||||
case CD_PROP_FLOAT4X4:
|
||||
return 9;
|
||||
#if 0 /* These attribute types are not supported yet. */
|
||||
case CD_PROP_STRING:
|
||||
return 6;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "BLI_math.h"
|
||||
#include "BLI_math_color_blend.h"
|
||||
#include "BLI_math_vector.hh"
|
||||
#include "BLI_math_matrix_types.hh"
|
||||
#include "BLI_mempool.h"
|
||||
#include "BLI_path_util.h"
|
||||
#include "BLI_set.hh"
|
||||
|
@ -1575,6 +1576,165 @@ static void layerInterp_propbool(const void **sources,
|
|||
*(bool *)dest = result;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Callbacks for ('float2x2', #CD_PROP_FLOAT2X2)
|
||||
* \{ */
|
||||
|
||||
static void layerInterp_propfloat2x2(const void **sources,
|
||||
const float *weights,
|
||||
const float * /*sub_weights*/,
|
||||
int count,
|
||||
void *dest)
|
||||
{
|
||||
float result[2][2] = {0.0f, 0.0f};
|
||||
for (int i = 0; i < count; i++) {
|
||||
const float interp_weight = weights[i];
|
||||
const float (*src)[2] = static_cast<const float (*)[2]>(sources[i]);
|
||||
madd_v4_v4fl((float *)result, (const float *)src, interp_weight);
|
||||
}
|
||||
copy_v4_v4((float *)dest, (float *)result);
|
||||
}
|
||||
|
||||
static void layerMultiply_propfloat2x2(void *data, const float fac)
|
||||
{
|
||||
mul_v4_fl((float *)data, fac);
|
||||
}
|
||||
|
||||
static void layerAdd_propfloat2x2(void *data1, const void *data2)
|
||||
{
|
||||
add_v4_v4((float *)data1, (const float *)data2);
|
||||
}
|
||||
|
||||
static bool layerValidate_propfloat2x2(void *data, const uint totitems, const bool do_fixes)
|
||||
{
|
||||
float *values = static_cast<float *>(data);
|
||||
bool has_errors = false;
|
||||
for (int i = 0; i < totitems * 4; i++) {
|
||||
if (!isfinite(values[i])) {
|
||||
if (do_fixes) {
|
||||
values[i] = 0.0f;
|
||||
}
|
||||
has_errors = true;
|
||||
}
|
||||
}
|
||||
return has_errors;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Callbacks for ('float3x3', #CD_PROP_FLOAT3X3)
|
||||
* \{ */
|
||||
|
||||
static void layerInterp_propfloat3x3(const void **sources,
|
||||
const float *weights,
|
||||
const float * /*sub_weights*/,
|
||||
int count,
|
||||
void *dest)
|
||||
{
|
||||
using blender::float3x3;
|
||||
|
||||
float3x3 result = float3x3::zero();
|
||||
for (int i = 0; i < count; i++) {
|
||||
const float interp_weight = weights[i];
|
||||
const float3x3 *src = static_cast<const float3x3 *>(sources[i]);
|
||||
madd_m3_m3m3fl(result.ptr(), result.ptr(), src->ptr(), interp_weight);
|
||||
}
|
||||
*static_cast<float3x3 *>(dest) = result.view();
|
||||
}
|
||||
|
||||
static void layerMultiply_propfloat3x3(void *data, const float fac)
|
||||
{
|
||||
using blender::float3x3;
|
||||
|
||||
float3x3 *mat = static_cast<float3x3 *>(data);
|
||||
mul_m3_fl(mat->ptr(), fac);
|
||||
}
|
||||
|
||||
static void layerAdd_propfloat3x3(void *data1, const void *data2)
|
||||
{
|
||||
using blender::float3x3;
|
||||
|
||||
float3x3 *mat1 = static_cast<float3x3 *>(data1);
|
||||
const float3x3 *mat2 = static_cast<const float3x3 *>(data2);
|
||||
add_m3_m3m3(mat1->ptr(), mat1->ptr(), mat2->ptr());
|
||||
}
|
||||
|
||||
static bool layerValidate_propfloat3x3(void *data, const uint totitems, const bool do_fixes)
|
||||
{
|
||||
float *values = static_cast<float *>(data);
|
||||
bool has_errors = false;
|
||||
for (int i = 0; i < totitems * 9; i++) {
|
||||
if (!isfinite(values[i])) {
|
||||
if (do_fixes) {
|
||||
values[i] = 0.0f;
|
||||
}
|
||||
has_errors = true;
|
||||
}
|
||||
}
|
||||
return has_errors;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Callbacks for ('float4x4', #CD_PROP_FLOAT4X4)
|
||||
* \{ */
|
||||
|
||||
static void layerInterp_propfloat4x4(const void **sources,
|
||||
const float *weights,
|
||||
const float * /*sub_weights*/,
|
||||
int count,
|
||||
void *dest)
|
||||
{
|
||||
using blender::float4x4;
|
||||
|
||||
float4x4 result;
|
||||
zero_m4(result.ptr());
|
||||
for (int i = 0; i < count; i++) {
|
||||
const float interp_weight = weights[i];
|
||||
const float4x4 *src = static_cast<const float4x4 *>(sources[i]);
|
||||
madd_m4_m4m4fl(result.ptr(), result.ptr(), src->ptr(), interp_weight);
|
||||
}
|
||||
*static_cast<float4x4 *>(dest) = result.view();
|
||||
}
|
||||
|
||||
static void layerMultiply_propfloat4x4(void *data, const float fac)
|
||||
{
|
||||
using blender::float4x4;
|
||||
|
||||
float4x4 *mat = static_cast<float4x4 *>(data);
|
||||
mul_m4_fl(mat->ptr(), fac);
|
||||
}
|
||||
|
||||
static void layerAdd_propfloat4x4(void *data1, const void *data2)
|
||||
{
|
||||
using blender::float4x4;
|
||||
|
||||
float4x4 *mat1 = static_cast<float4x4 *>(data1);
|
||||
const float4x4 *mat2 = static_cast<const float4x4 *>(data2);
|
||||
add_m4_m4m4(mat1->ptr(), mat1->ptr(), mat2->ptr());
|
||||
}
|
||||
|
||||
static bool layerValidate_propfloat4x4(void *data, const uint totitems, const bool do_fixes)
|
||||
{
|
||||
float *values = static_cast<float *>(data);
|
||||
bool has_errors = false;
|
||||
for (int i = 0; i < totitems * 16; i++) {
|
||||
if (!isfinite(values[i])) {
|
||||
if (do_fixes) {
|
||||
values[i] = 0.0f;
|
||||
}
|
||||
has_errors = true;
|
||||
}
|
||||
}
|
||||
return has_errors;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
||||
/* 0: CD_MVERT */ /* DEPRECATED */
|
||||
{sizeof(MVert), "MVert", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
|
@ -1966,6 +2126,54 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
nullptr},
|
||||
/* 51: CD_HAIRLENGTH */
|
||||
{sizeof(float), "float", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
/* 52: CD_PROP_FLOAT2X2 */
|
||||
{sizeof(float[2][2]),
|
||||
"float2x2",
|
||||
1,
|
||||
N_("Float2x2"),
|
||||
nullptr,
|
||||
nullptr,
|
||||
layerInterp_propfloat2x2,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
layerValidate_propfloat2x2,
|
||||
nullptr,
|
||||
layerMultiply_propfloat2x2,
|
||||
nullptr,
|
||||
layerAdd_propfloat2x2},
|
||||
/* 53: CD_PROP_FLOAT3X3 */
|
||||
{sizeof(float[3][3]),
|
||||
"float3x3",
|
||||
1,
|
||||
N_("Float3x3"),
|
||||
nullptr,
|
||||
nullptr,
|
||||
layerInterp_propfloat3x3,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
layerValidate_propfloat3x3,
|
||||
nullptr,
|
||||
layerMultiply_propfloat3x3,
|
||||
nullptr,
|
||||
layerAdd_propfloat3x3},
|
||||
/* 54: CD_PROP_FLOAT4X4 */
|
||||
{sizeof(float[4][4]),
|
||||
"float4x4",
|
||||
1,
|
||||
N_("Float4x4"),
|
||||
nullptr,
|
||||
nullptr,
|
||||
layerInterp_propfloat4x4,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
layerValidate_propfloat4x4,
|
||||
nullptr,
|
||||
layerMultiply_propfloat4x4,
|
||||
nullptr,
|
||||
layerAdd_propfloat4x4},
|
||||
};
|
||||
|
||||
static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
|
||||
|
@ -2023,6 +2231,9 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
|
|||
"CDPropFloat2",
|
||||
"CDPropBoolean",
|
||||
"CDHairLength",
|
||||
"CDPropFloat2x2",
|
||||
"CDPropFloat3x3",
|
||||
"CDPropFloat4x4",
|
||||
};
|
||||
|
||||
const CustomData_MeshMasks CD_MASK_BAREMESH = {
|
||||
|
@ -5161,6 +5372,10 @@ const blender::CPPType *custom_data_type_to_cpp_type(const eCustomDataType type)
|
|||
return &CPPType::get<float2>();
|
||||
case CD_PROP_FLOAT3:
|
||||
return &CPPType::get<float3>();
|
||||
case CD_PROP_FLOAT3X3:
|
||||
return &CPPType::get<float3x3>();
|
||||
case CD_PROP_FLOAT4X4:
|
||||
return &CPPType::get<float4x4>();
|
||||
case CD_PROP_INT32:
|
||||
return &CPPType::get<int>();
|
||||
case CD_PROP_COLOR:
|
||||
|
@ -5189,6 +5404,12 @@ eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
|
|||
if (type.is<float3>()) {
|
||||
return CD_PROP_FLOAT3;
|
||||
}
|
||||
if (type.is<float3x3>()) {
|
||||
return CD_PROP_FLOAT3X3;
|
||||
}
|
||||
if (type.is<float4x4>()) {
|
||||
return CD_PROP_FLOAT4X4;
|
||||
}
|
||||
if (type.is<int>()) {
|
||||
return CD_PROP_INT32;
|
||||
}
|
||||
|
|
|
@ -317,6 +317,7 @@ static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket
|
|||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_MATRIX:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -456,6 +457,9 @@ static void write_node_socket_default_value(BlendWriter *writer, bNodeSocket *so
|
|||
case SOCK_MATERIAL:
|
||||
BLO_write_struct(writer, bNodeSocketValueMaterial, sock->default_value);
|
||||
break;
|
||||
case SOCK_MATRIX:
|
||||
BLO_write_struct(writer, bNodeSocketValueMatrix, sock->default_value);
|
||||
break;
|
||||
case SOCK_CUSTOM:
|
||||
/* Custom node sockets where default_value is defined uses custom properties for storage. */
|
||||
break;
|
||||
|
@ -881,6 +885,7 @@ static void lib_link_node_socket(BlendLibReader *reader, Library *lib, bNodeSock
|
|||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_MATRIX:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -980,6 +985,7 @@ static void expand_node_socket(BlendExpander *expander, bNodeSocket *sock)
|
|||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_MATRIX:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1596,6 +1602,7 @@ static void socket_id_user_increment(bNodeSocket *sock)
|
|||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_MATRIX:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1655,6 +1662,7 @@ static bool socket_id_user_decrement(bNodeSocket *sock)
|
|||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_MATRIX:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
@ -1799,6 +1807,8 @@ const char *nodeStaticSocketType(const int type, const int subtype)
|
|||
return "NodeSocketTexture";
|
||||
case SOCK_MATERIAL:
|
||||
return "NodeSocketMaterial";
|
||||
case SOCK_MATRIX:
|
||||
return "NodeSocketMatrix";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1876,6 +1886,8 @@ const char *nodeStaticSocketInterfaceType(const int type, const int subtype)
|
|||
return "NodeSocketInterfaceTexture";
|
||||
case SOCK_MATERIAL:
|
||||
return "NodeSocketInterfaceMaterial";
|
||||
case SOCK_MATRIX:
|
||||
return "NodeSocketInterfaceMatrix";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1909,6 +1921,8 @@ const char *nodeStaticSocketLabel(const int type, const int /*subtype*/)
|
|||
return "Texture";
|
||||
case SOCK_MATERIAL:
|
||||
return "Material";
|
||||
case SOCK_MATRIX:
|
||||
return "Matrix";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ using nodes::SocketDeclaration;
|
|||
|
||||
static bool is_field_socket_type(eNodeSocketDatatype type)
|
||||
{
|
||||
return ELEM(type, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, SOCK_VECTOR, SOCK_RGBA);
|
||||
return ELEM(type, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, SOCK_VECTOR, SOCK_RGBA, SOCK_MATRIX);
|
||||
}
|
||||
|
||||
static bool is_field_socket_type(const bNodeSocket &socket)
|
||||
|
|
|
@ -47,6 +47,7 @@ BLI_CPP_TYPE_MAKE(bool, CPPTypeFlags::BasicType)
|
|||
BLI_CPP_TYPE_MAKE(float, CPPTypeFlags::BasicType)
|
||||
BLI_CPP_TYPE_MAKE(blender::float2, CPPTypeFlags::BasicType)
|
||||
BLI_CPP_TYPE_MAKE(blender::float3, CPPTypeFlags::BasicType)
|
||||
BLI_CPP_TYPE_MAKE(blender::float3x3, CPPTypeFlags::BasicType)
|
||||
BLI_CPP_TYPE_MAKE(blender::float4x4, CPPTypeFlags::BasicType)
|
||||
|
||||
BLI_CPP_TYPE_MAKE(int8_t, CPPTypeFlags::BasicType)
|
||||
|
@ -75,6 +76,7 @@ void register_cpp_types()
|
|||
BLI_CPP_TYPE_REGISTER(float);
|
||||
BLI_CPP_TYPE_REGISTER(blender::float2);
|
||||
BLI_CPP_TYPE_REGISTER(blender::float3);
|
||||
BLI_CPP_TYPE_REGISTER(blender::float3x3);
|
||||
BLI_CPP_TYPE_REGISTER(blender::float4x4);
|
||||
|
||||
BLI_CPP_TYPE_REGISTER(int8_t);
|
||||
|
|
|
@ -5823,7 +5823,7 @@ void uiLayoutSetTooltipFunc(uiLayout *layout,
|
|||
}
|
||||
}
|
||||
|
||||
if (!arg_used) {
|
||||
if (!arg_used && free_arg) {
|
||||
/* Free the original copy of arg in case the layout is empty. */
|
||||
free_arg(arg);
|
||||
}
|
||||
|
|
|
@ -1200,6 +1200,7 @@ static const float std_node_socket_colors[][4] = {
|
|||
{0.96, 0.96, 0.96, 1.0}, /* SOCK_COLLECTION */
|
||||
{0.62, 0.31, 0.64, 1.0}, /* SOCK_TEXTURE */
|
||||
{0.92, 0.46, 0.51, 1.0}, /* SOCK_MATERIAL */
|
||||
{0.01, 0.61, 0.66, 1.0}, /* SOCK_MATRIX */
|
||||
};
|
||||
|
||||
/* common color callbacks for standard types */
|
||||
|
@ -1321,6 +1322,15 @@ static void std_node_socket_draw(
|
|||
}
|
||||
}
|
||||
break;
|
||||
case SOCK_MATRIX:
|
||||
if (sock->flag & SOCK_COMPACT) {
|
||||
uiTemplateComponentMenu(layout, ptr, "default_value", text);
|
||||
}
|
||||
else {
|
||||
uiLayout *column = uiLayoutColumn(layout, true);
|
||||
uiItemR(column, ptr, "default_value", DEFAULT_FLAGS, text, ICON_NONE);
|
||||
}
|
||||
break;
|
||||
case SOCK_RGBA: {
|
||||
if (text[0] == '\0') {
|
||||
uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, "", 0);
|
||||
|
@ -1451,6 +1461,13 @@ static void std_node_socket_interface_draw(bContext * /*C*/, uiLayout *layout, P
|
|||
uiItemR(sub, ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), ICON_NONE);
|
||||
break;
|
||||
}
|
||||
case SOCK_MATRIX: {
|
||||
uiItemR(col, ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), ICON_NONE);
|
||||
uiLayout *sub = uiLayoutColumn(col, true);
|
||||
uiItemR(sub, ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), ICON_NONE);
|
||||
uiItemR(sub, ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), ICON_NONE);
|
||||
break;
|
||||
}
|
||||
case SOCK_BOOLEAN:
|
||||
case SOCK_RGBA:
|
||||
case SOCK_STRING:
|
||||
|
|
|
@ -448,6 +448,8 @@ static eCustomDataType socket_type_to_custom_data_type(const eNodeSocketDatatype
|
|||
return CD_PROP_INT32;
|
||||
case SOCK_VECTOR:
|
||||
return CD_PROP_FLOAT3;
|
||||
case SOCK_MATRIX:
|
||||
return CD_PROP_FLOAT4X4;
|
||||
case SOCK_BOOLEAN:
|
||||
return CD_PROP_BOOL;
|
||||
case SOCK_RGBA:
|
||||
|
@ -2212,6 +2214,7 @@ static int get_main_socket_priority(const bNodeSocket *socket)
|
|||
case SOCK_COLLECTION:
|
||||
case SOCK_TEXTURE:
|
||||
case SOCK_MATERIAL:
|
||||
case SOCK_MATRIX:
|
||||
return 6;
|
||||
}
|
||||
return -1;
|
||||
|
|
|
@ -381,6 +381,9 @@ static Vector<NodeLinkItem> ui_node_link_items(NodeLinkArg *arg,
|
|||
else if (dynamic_cast<const decl::Vector *>(&socket_decl)) {
|
||||
item.socket_type = SOCK_VECTOR;
|
||||
}
|
||||
else if (dynamic_cast<const decl::Matrix *>(&socket_decl)) {
|
||||
item.socket_type = SOCK_MATRIX;
|
||||
}
|
||||
else if (dynamic_cast<const decl::Color *>(&socket_decl)) {
|
||||
item.socket_type = SOCK_RGBA;
|
||||
}
|
||||
|
@ -861,6 +864,7 @@ static void ui_node_draw_input(
|
|||
else {
|
||||
switch (input.type) {
|
||||
case SOCK_VECTOR:
|
||||
case SOCK_MATRIX:
|
||||
uiItemS(sub);
|
||||
sub = uiLayoutColumn(sub, true);
|
||||
ATTR_FALLTHROUGH;
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
FN_FIELD_CPP_TYPE_MAKE(float);
|
||||
FN_FIELD_CPP_TYPE_MAKE(blender::float2);
|
||||
FN_FIELD_CPP_TYPE_MAKE(blender::float3);
|
||||
FN_FIELD_CPP_TYPE_MAKE(blender::float3x3);
|
||||
FN_FIELD_CPP_TYPE_MAKE(blender::float4x4);
|
||||
FN_FIELD_CPP_TYPE_MAKE(blender::ColorGeometry4f);
|
||||
FN_FIELD_CPP_TYPE_MAKE(blender::ColorGeometry4b);
|
||||
FN_FIELD_CPP_TYPE_MAKE(bool);
|
||||
|
@ -26,6 +28,8 @@ void FN_register_cpp_types()
|
|||
FN_FIELD_CPP_TYPE_REGISTER(float);
|
||||
FN_FIELD_CPP_TYPE_REGISTER(blender::float2);
|
||||
FN_FIELD_CPP_TYPE_REGISTER(blender::float3);
|
||||
FN_FIELD_CPP_TYPE_REGISTER(blender::float3x3);
|
||||
FN_FIELD_CPP_TYPE_REGISTER(blender::float4x4);
|
||||
FN_FIELD_CPP_TYPE_REGISTER(blender::ColorGeometry4f);
|
||||
FN_FIELD_CPP_TYPE_REGISTER(blender::ColorGeometry4b);
|
||||
FN_FIELD_CPP_TYPE_REGISTER(bool);
|
||||
|
|
|
@ -76,8 +76,7 @@ typedef struct CustomData {
|
|||
* MUST be >= CD_NUMTYPES, but we can't use a define here.
|
||||
* Correct size is ensured in CustomData_update_typemap assert().
|
||||
*/
|
||||
int typemap[52];
|
||||
char _pad[4];
|
||||
int typemap[55];
|
||||
/** Number of layers, size of layers array. */
|
||||
int totlayer, maxlayer;
|
||||
/** In editmode, total size of all data layers. */
|
||||
|
@ -163,7 +162,11 @@ typedef enum eCustomDataType {
|
|||
|
||||
CD_HAIRLENGTH = 51,
|
||||
|
||||
CD_NUMTYPES = 52,
|
||||
CD_PROP_FLOAT2X2 = 52,
|
||||
CD_PROP_FLOAT3X3 = 53,
|
||||
CD_PROP_FLOAT4X4 = 54,
|
||||
|
||||
CD_NUMTYPES = 55,
|
||||
} eCustomDataType;
|
||||
|
||||
/* Bits for eCustomDataMask */
|
||||
|
@ -216,6 +219,10 @@ typedef enum eCustomDataType {
|
|||
|
||||
#define CD_MASK_HAIRLENGTH (1ULL << CD_HAIRLENGTH)
|
||||
|
||||
#define CD_MASK_FLOAT2X2 (1ULL << CD_PROP_FLOAT2X2)
|
||||
#define CD_MASK_FLOAT3X3 (1ULL << CD_PROP_FLOAT3X3)
|
||||
#define CD_MASK_FLOAT4X4 (1ULL << CD_PROP_FLOAT4X4)
|
||||
|
||||
/** Multi-resolution loop data. */
|
||||
#define CD_MASK_MULTIRES_GRIDS (CD_MASK_MDISPS | CD_GRID_PAINT_MASK)
|
||||
|
||||
|
@ -226,7 +233,7 @@ typedef enum eCustomDataType {
|
|||
#define CD_MASK_PROP_ALL \
|
||||
(CD_MASK_PROP_FLOAT | CD_MASK_PROP_FLOAT2 | CD_MASK_PROP_FLOAT3 | CD_MASK_PROP_INT32 | \
|
||||
CD_MASK_PROP_COLOR | CD_MASK_PROP_STRING | CD_MASK_PROP_BYTE_COLOR | CD_MASK_PROP_BOOL | \
|
||||
CD_MASK_PROP_INT8)
|
||||
CD_MASK_PROP_INT8 | CD_MASK_FLOAT2X2 | CD_MASK_FLOAT3X3 | CD_MASK_FLOAT4X4)
|
||||
|
||||
/* All color attributes */
|
||||
#define CD_MASK_COLOR_ALL (CD_MASK_PROP_COLOR | CD_MASK_PROP_BYTE_COLOR)
|
||||
|
|
|
@ -235,6 +235,7 @@ typedef enum eNodeSocketDatatype {
|
|||
SOCK_COLLECTION = 11,
|
||||
SOCK_TEXTURE = 12,
|
||||
SOCK_MATERIAL = 13,
|
||||
SOCK_MATRIX = 14,
|
||||
} eNodeSocketDatatype;
|
||||
|
||||
/** Socket shape. */
|
||||
|
@ -714,6 +715,11 @@ typedef struct bNodeSocketValueVector {
|
|||
float min, max;
|
||||
} bNodeSocketValueVector;
|
||||
|
||||
typedef struct bNodeSocketValueMatrix {
|
||||
float value[4][4];
|
||||
float min, max;
|
||||
} bNodeSocketValueMatrix;
|
||||
|
||||
typedef struct bNodeSocketValueRGBA {
|
||||
float value[4];
|
||||
} bNodeSocketValueRGBA;
|
||||
|
@ -1620,6 +1626,10 @@ typedef struct NodeShaderMix {
|
|||
char _pad[3];
|
||||
} NodeShaderMix;
|
||||
|
||||
typedef struct NodeInputMatrix {
|
||||
float matrix[4][4];
|
||||
} NodeInputMatrix;
|
||||
|
||||
/* script node mode */
|
||||
#define NODE_SCRIPT_INTERNAL 0
|
||||
#define NODE_SCRIPT_EXTERNAL 1
|
||||
|
@ -1895,6 +1905,26 @@ typedef enum NodeVectorMathOperation {
|
|||
NODE_VECTOR_MATH_MULTIPLY_ADD = 26,
|
||||
} NodeVectorMathOperation;
|
||||
|
||||
typedef enum NodeMatrixMathOperation {
|
||||
NODE_MATRIX_MATH_ADD = 0,
|
||||
NODE_MATRIX_MATH_SUBTRACT = 1,
|
||||
NODE_MATRIX_MATH_SCALAR_MULTIPLY = 2,
|
||||
NODE_MATRIX_MATH_MULTIPLY = 3,
|
||||
NODE_MATRIX_MATH_TRANSPOSE = 4,
|
||||
NODE_MATRIX_MATH_INVERSE = 5,
|
||||
NODE_MATRIX_MATH_DETERMINANT = 6,
|
||||
NODE_MATRIX_MATH_TRACE = 7,
|
||||
//NODE_MATRIX_MATH_IS_SYMMETRIC = 8,
|
||||
//NODE_MATRIX_MATH_IS_ANTI_SYMMETRIC = 9,
|
||||
//NODE_MATRIX_MATH_IS_ORTHOGONAL = 10,
|
||||
} NodeMatrixMathOperation;
|
||||
|
||||
typedef enum NodeMatrixTransformVectorMode {
|
||||
NODE_MATRIX_TRANSFORM_POINT = 0,
|
||||
NODE_MATRIX_TRANSFORM_DIRECTION = 1,
|
||||
NODE_MATRIX_TRANSFORM_NORMAL = 2,
|
||||
} NodeMatrixTransformVectorMode;
|
||||
|
||||
typedef enum NodeBooleanMathOperation {
|
||||
NODE_BOOLEAN_MATH_AND = 0,
|
||||
NODE_BOOLEAN_MATH_OR = 1,
|
||||
|
@ -2397,3 +2427,9 @@ typedef enum NodeCombSepColorMode {
|
|||
NODE_COMBSEP_COLOR_HSV = 1,
|
||||
NODE_COMBSEP_COLOR_HSL = 2,
|
||||
} NodeCombSepColorMode;
|
||||
|
||||
typedef enum NodeCombSepMatrixMode {
|
||||
NODE_COMBSEP_MATRIX_COLUMNS = 0,
|
||||
NODE_COMBSEP_MATRIX_ROWS = 1,
|
||||
NODE_COMBSEP_MATRIX_ELEMENTS = 2,
|
||||
} NodeCombSepMatrixMode;
|
||||
|
|
|
@ -62,6 +62,7 @@ static const EnumPropertyItem node_socket_data_type_items[] = {
|
|||
{SOCK_INT, "INT", 0, "Integer", ""},
|
||||
{SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""},
|
||||
{SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
|
||||
{SOCK_MATRIX, "MATRIX", 0, "Matrix", ""},
|
||||
{SOCK_STRING, "STRING", 0, "String", ""},
|
||||
{SOCK_RGBA, "RGBA", 0, "Color", ""},
|
||||
{SOCK_OBJECT, "OBJECT", 0, "Object", ""},
|
||||
|
@ -89,6 +90,7 @@ static const EnumPropertyItem node_socket_type_items[] = {
|
|||
{SOCK_INT, "INT", 0, "Integer", ""},
|
||||
{SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""},
|
||||
{SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
|
||||
{SOCK_MATRIX, "MATRIX", 0, "Matrix", ""},
|
||||
{SOCK_STRING, "STRING", 0, "String", ""},
|
||||
{SOCK_RGBA, "RGBA", 0, "RGBA", ""},
|
||||
{SOCK_SHADER, "SHADER", 0, "Shader", ""},
|
||||
|
@ -288,6 +290,31 @@ const EnumPropertyItem rna_enum_node_vec_math_items[] = {
|
|||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
const EnumPropertyItem rna_enum_node_matrix_math_items[] = {
|
||||
{NODE_MATRIX_MATH_ADD, "ADD", 0, "Add", ""},
|
||||
{NODE_MATRIX_MATH_SUBTRACT, "SUBTRACT", 0, "Subtract", ""},
|
||||
{NODE_MATRIX_MATH_SCALAR_MULTIPLY, "SCALAR_MULTIPLY", 0, "Scalar Multiply", ""},
|
||||
{NODE_MATRIX_MATH_MULTIPLY, "MULTIPLY", 0, "Multiply", ""},
|
||||
RNA_ENUM_ITEM_SEPR,
|
||||
{NODE_MATRIX_MATH_TRANSPOSE, "TRANSPOSE", 0, "Transpose", ""},
|
||||
{NODE_MATRIX_MATH_INVERSE, "INVERSE", 0, "Inverse", ""},
|
||||
RNA_ENUM_ITEM_SEPR,
|
||||
{NODE_MATRIX_MATH_DETERMINANT, "DETERMINANT", 0, "Determinant", ""},
|
||||
{NODE_MATRIX_MATH_TRACE, "TRACE", 0, "Trace", ""},
|
||||
//RNA_ENUM_ITEM_SEPR,
|
||||
//{NODE_MATRIX_MATH_IS_SYMMETRIC, "IS_SYMMETRIC", 0, "Is Symmetric", ""},
|
||||
//{NODE_MATRIX_MATH_IS_ANTI_SYMMETRIC, "IS_ANTI_SYMMETRIC", 0, "Is Anti-Symmetric", ""},
|
||||
//{NODE_MATRIX_MATH_IS_ORTHOGONAL, "IS_ORTHOGONAL", 0, "Is Orthogonal", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
const EnumPropertyItem rna_enum_node_matrix_transform_vector_mode_items[] = {
|
||||
{NODE_MATRIX_TRANSFORM_POINT, "POINT", 0, "Point", "Apply translation, rotation and scale"},
|
||||
{NODE_MATRIX_TRANSFORM_DIRECTION, "DIRECTION", 0, "Direction", "Apply only rotation and scale"},
|
||||
{NODE_MATRIX_TRANSFORM_NORMAL, "NORMAL", 0, "Normal", "Apply inverse transpose of the matrix for surface normals"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
const EnumPropertyItem rna_enum_node_boolean_math_items[] = {
|
||||
{NODE_BOOLEAN_MATH_AND, "AND", 0, "And", "True when both inputs are true"},
|
||||
{NODE_BOOLEAN_MATH_OR, "OR", 0, "Or", "True when at least one input is true"},
|
||||
|
@ -499,6 +526,13 @@ static const EnumPropertyItem rna_node_combsep_color_items[] = {
|
|||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem rna_node_combsep_matrix_items[] = {
|
||||
{NODE_COMBSEP_MATRIX_COLUMNS, "COLUMNS", ICON_NONE, "Columns", "Use vectors as matrix columns"},
|
||||
{NODE_COMBSEP_MATRIX_ROWS, "ROWS", ICON_NONE, "Rows", "Use vectors as matrix rows"},
|
||||
{NODE_COMBSEP_MATRIX_ELEMENTS, "ELEMENTS", ICON_NONE, "Elements", "Use individual matrix elements"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
#ifndef RNA_RUNTIME
|
||||
static const EnumPropertyItem node_sampler_type_items[] = {
|
||||
{0, "NEAREST", 0, "Nearest", ""},
|
||||
|
@ -3263,6 +3297,22 @@ static void rna_NodeSocketStandard_vector_range(
|
|||
*softmax = dval->max;
|
||||
}
|
||||
|
||||
static void rna_NodeSocketStandard_matrix_range(
|
||||
PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
|
||||
{
|
||||
bNodeSocket *sock = ptr->data;
|
||||
bNodeSocketValueMatrix *dval = sock->default_value;
|
||||
|
||||
if (dval->max < dval->min) {
|
||||
dval->max = dval->min;
|
||||
}
|
||||
|
||||
*min = -FLT_MAX;
|
||||
*max = FLT_MAX;
|
||||
*softmin = dval->min;
|
||||
*softmax = dval->max;
|
||||
}
|
||||
|
||||
/* using a context update function here, to avoid searching the node if possible */
|
||||
static void rna_NodeSocketStandard_value_update(struct bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
|
@ -5193,6 +5243,71 @@ static void def_fn_combsep_color(StructRNA *srna)
|
|||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
}
|
||||
|
||||
static void def_fn_input_matrix(StructRNA *srna)
|
||||
{
|
||||
static const float default_elements[] = {
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
};
|
||||
PropertyRNA *prop;
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "NodeInputMatrix", "storage");
|
||||
|
||||
prop = RNA_def_property(srna, "matrix", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_float_sdna(prop, NULL, "matrix");
|
||||
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
|
||||
RNA_def_property_float_array_default(prop, default_elements);
|
||||
RNA_def_property_ui_text(prop, "Matrix", "Input value used for unconnected socket");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void def_fn_combsep_matrix(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "custom1");
|
||||
RNA_def_property_enum_items(prop, rna_node_combsep_matrix_items);
|
||||
RNA_def_property_ui_text(prop, "Mode", "Mode of matrix composition");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
}
|
||||
|
||||
static void def_fn_matrix_math(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "custom1");
|
||||
RNA_def_property_enum_items(prop, rna_enum_node_matrix_math_items);
|
||||
RNA_def_property_ui_text(prop, "Operation", "");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
}
|
||||
|
||||
static void def_fn_matrix_transform(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_property(srna, "vector_mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "custom1");
|
||||
RNA_def_property_enum_items(prop, rna_enum_node_matrix_transform_vector_mode_items);
|
||||
RNA_def_property_ui_text(prop, "Vector Mode", "");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
}
|
||||
|
||||
/* -- Shader Nodes ---------------------------------------------------------- */
|
||||
|
||||
static void def_sh_output(StructRNA *srna)
|
||||
|
@ -11558,6 +11673,74 @@ static void rna_def_node_socket_vector(BlenderRNA *brna,
|
|||
RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
|
||||
}
|
||||
|
||||
static void rna_def_node_socket_matrix(BlenderRNA *brna,
|
||||
const char *identifier,
|
||||
const char *interface_idname)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
const float value_default[] = {1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f};
|
||||
|
||||
srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
|
||||
RNA_def_struct_ui_text(srna, "Matrix Node Socket", "Matrix socket of a node");
|
||||
RNA_def_struct_sdna(srna, "bNodeSocket");
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bNodeSocketValueMatrix", "default_value");
|
||||
|
||||
prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_float_sdna(prop, NULL, "value");
|
||||
RNA_def_property_float_array_default(prop, value_default);
|
||||
RNA_def_property_float_funcs(prop, NULL, NULL, "rna_NodeSocketStandard_matrix_range");
|
||||
RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
|
||||
|
||||
/* socket interface */
|
||||
srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
|
||||
RNA_def_struct_ui_text(srna, "Matrix Node Socket Interface", "Matrix socket of a node");
|
||||
RNA_def_struct_sdna(srna, "bNodeSocket");
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bNodeSocketValueMatrix", "default_value");
|
||||
|
||||
prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_float_sdna(prop, NULL, "value");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_float_funcs(prop, NULL, NULL, "rna_NodeSocketStandard_matrix_range");
|
||||
RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update");
|
||||
|
||||
prop = RNA_def_property(srna, "min_value", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "min");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Minimum Value", "Minimum value");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update");
|
||||
|
||||
prop = RNA_def_property(srna, "max_value", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "max");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Maximum Value", "Maximum value");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update");
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
|
||||
}
|
||||
|
||||
static void rna_def_node_socket_color(BlenderRNA *brna,
|
||||
const char *identifier,
|
||||
const char *interface_idname)
|
||||
|
@ -11999,6 +12182,8 @@ static void rna_def_node_socket_standard_types(BlenderRNA *brna)
|
|||
rna_def_node_socket_vector(
|
||||
brna, "NodeSocketVectorXYZ", "NodeSocketInterfaceVectorXYZ", PROP_XYZ);
|
||||
|
||||
rna_def_node_socket_matrix(brna, "NodeSocketMatrix", "NodeSocketInterfaceMatrix");
|
||||
|
||||
rna_def_node_socket_color(brna, "NodeSocketColor", "NodeSocketInterfaceColor");
|
||||
|
||||
rna_def_node_socket_string(brna, "NodeSocketString", "NodeSocketInterfaceString");
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "BLI_array.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_matrix_types.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_multi_value_map.hh"
|
||||
#include "BLI_set.hh"
|
||||
|
@ -100,6 +101,8 @@ using blender::ColorGeometry4f;
|
|||
using blender::CPPType;
|
||||
using blender::destruct_ptr;
|
||||
using blender::float3;
|
||||
using blender::float3x3;
|
||||
using blender::float4x4;
|
||||
using blender::FunctionRef;
|
||||
using blender::GMutablePointer;
|
||||
using blender::GMutableSpan;
|
||||
|
@ -416,7 +419,7 @@ static const std::string attribute_name_suffix = "_attribute_name";
|
|||
*/
|
||||
static bool socket_type_has_attribute_toggle(const bNodeSocket &socket)
|
||||
{
|
||||
return ELEM(socket.type, SOCK_FLOAT, SOCK_VECTOR, SOCK_BOOLEAN, SOCK_RGBA, SOCK_INT);
|
||||
return ELEM(socket.type, SOCK_FLOAT, SOCK_VECTOR, SOCK_BOOLEAN, SOCK_RGBA, SOCK_INT, SOCK_MATRIX);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -474,6 +477,22 @@ id_property_create_from_socket(const bNodeSocket &socket)
|
|||
}
|
||||
return property;
|
||||
}
|
||||
case SOCK_MATRIX: {
|
||||
const bNodeSocketValueMatrix *value = static_cast<const bNodeSocketValueMatrix *>(
|
||||
socket.default_value);
|
||||
const Span<float> default_value_span((float *)value->value, 16);
|
||||
auto property = bke::idprop::create(socket.identifier, default_value_span);
|
||||
IDPropertyUIDataFloat *ui_data = (IDPropertyUIDataFloat *)IDP_ui_data_ensure(property.get());
|
||||
ui_data->base.rna_subtype = PROP_MATRIX;
|
||||
ui_data->min = ui_data->soft_min = double(value->min);
|
||||
ui_data->max = ui_data->soft_max = double(value->max);
|
||||
ui_data->default_array = (double *)MEM_mallocN(sizeof(double[16]), "mod_prop_default");
|
||||
ui_data->default_array_len = 16;
|
||||
for (const int i : IndexRange(16)) {
|
||||
ui_data->default_array[i] = double(default_value_span[i]);
|
||||
}
|
||||
return property;
|
||||
}
|
||||
case SOCK_RGBA: {
|
||||
const bNodeSocketValueRGBA *value = static_cast<const bNodeSocketValueRGBA *>(
|
||||
socket.default_value);
|
||||
|
@ -551,6 +570,8 @@ static bool id_property_type_matches_socket(const bNodeSocket &socket, const IDP
|
|||
return property.type == IDP_INT;
|
||||
case SOCK_VECTOR:
|
||||
return property.type == IDP_ARRAY && property.subtype == IDP_FLOAT && property.len == 3;
|
||||
case SOCK_MATRIX:
|
||||
return property.type == IDP_ARRAY && property.subtype == IDP_FLOAT && property.len == 16;
|
||||
case SOCK_RGBA:
|
||||
return property.type == IDP_ARRAY && property.subtype == IDP_FLOAT && property.len == 4;
|
||||
case SOCK_BOOLEAN:
|
||||
|
@ -595,6 +616,12 @@ static void init_socket_cpp_value_from_property(const IDProperty &property,
|
|||
new (r_value) ValueOrField<float3>(value);
|
||||
break;
|
||||
}
|
||||
case SOCK_MATRIX: {
|
||||
float4x4 value;
|
||||
copy_m4_m4(value.ptr(), (const float(*)[4])IDP_Array(&property));
|
||||
new (r_value) ValueOrField<float4x4>(value);
|
||||
break;
|
||||
}
|
||||
case SOCK_RGBA: {
|
||||
blender::ColorGeometry4f value;
|
||||
copy_v4_v4((float *)value, (const float *)IDP_Array(&property));
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "RNA_types.h"
|
||||
|
||||
#include "BLI_color.hh"
|
||||
#include "BLI_math_matrix_types.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
namespace blender::nodes::decl {
|
||||
|
@ -93,6 +94,32 @@ class VectorBuilder : public SocketDeclarationBuilder<Vector> {
|
|||
VectorBuilder &compact();
|
||||
};
|
||||
|
||||
class MatrixBuilder;
|
||||
|
||||
class Matrix : public SocketDeclaration {
|
||||
private:
|
||||
float4x4 default_value_ = float4x4::identity();
|
||||
float soft_min_value_ = -FLT_MAX;
|
||||
float soft_max_value_ = FLT_MAX;
|
||||
|
||||
friend MatrixBuilder;
|
||||
|
||||
public:
|
||||
using Builder = MatrixBuilder;
|
||||
|
||||
bNodeSocket &build(bNodeTree &ntree, bNode &node) const override;
|
||||
bool matches(const bNodeSocket &socket) const override;
|
||||
bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override;
|
||||
bool can_connect(const bNodeSocket &socket) const override;
|
||||
};
|
||||
|
||||
class MatrixBuilder : public SocketDeclarationBuilder<Matrix> {
|
||||
public:
|
||||
MatrixBuilder &default_value(const float4x4 &value);
|
||||
MatrixBuilder &min(float min);
|
||||
MatrixBuilder &max(float max);
|
||||
};
|
||||
|
||||
class BoolBuilder;
|
||||
|
||||
class Bool : public SocketDeclaration {
|
||||
|
@ -343,6 +370,30 @@ inline VectorBuilder &VectorBuilder::compact()
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #MatrixBuilder Inline Methods
|
||||
* \{ */
|
||||
|
||||
inline MatrixBuilder &MatrixBuilder::default_value(const float4x4 &value)
|
||||
{
|
||||
decl_->default_value_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline MatrixBuilder &MatrixBuilder::min(const float min)
|
||||
{
|
||||
decl_->soft_min_value_ = min;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline MatrixBuilder &MatrixBuilder::max(const float max)
|
||||
{
|
||||
decl_->soft_max_value_ = max;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #BoolBuilder Inline Methods
|
||||
* \{ */
|
||||
|
|
|
@ -264,20 +264,29 @@ DefNode(TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DI
|
|||
DefNode(FunctionNode, FN_NODE_ALIGN_EULER_TO_VECTOR, def_fn_align_euler_to_vector, "ALIGN_EULER_TO_VECTOR", AlignEulerToVector, "Align Euler to Vector", "")
|
||||
DefNode(FunctionNode, FN_NODE_BOOLEAN_MATH, def_boolean_math, "BOOLEAN_MATH", BooleanMath, "Boolean Math", "")
|
||||
DefNode(FunctionNode, FN_NODE_COMBINE_COLOR, def_fn_combsep_color, "COMBINE_COLOR", CombineColor, "Combine Color", "")
|
||||
DefNode(FunctionNode, FN_NODE_COMBINE_MATRIX, def_fn_combsep_matrix, "COMBINE_MATRIX", CombineMatrix, "Combine Matrix", "")
|
||||
DefNode(FunctionNode, FN_NODE_COMPARE, def_compare, "COMPARE", Compare, "Compare", "")
|
||||
DefNode(FunctionNode, FN_NODE_DECOMPOSE_MATRIX, 0, "DECOMPOSE_MATRIX", DecomposeMatrix, "Decompose Matrix", "")
|
||||
DefNode(FunctionNode, FN_NODE_FLOAT_TO_INT, def_float_to_int, "FLOAT_TO_INT", FloatToInt, "Float to Integer", "")
|
||||
DefNode(FunctionNode, FN_NODE_INPUT_BOOL, def_fn_input_bool, "INPUT_BOOL", InputBool, "Boolean", "")
|
||||
DefNode(FunctionNode, FN_NODE_INPUT_COLOR, def_fn_input_color, "INPUT_COLOR", InputColor, "Color", "")
|
||||
DefNode(FunctionNode, FN_NODE_INPUT_INT, def_fn_input_int, "INPUT_INT", InputInt, "Integer", "")
|
||||
DefNode(FunctionNode, FN_NODE_INPUT_MATRIX, def_fn_input_matrix, "INPUT_MATRIX", InputMatrix, "Matrix", "")
|
||||
DefNode(FunctionNode, FN_NODE_INPUT_SPECIAL_CHARACTERS, 0, "INPUT_SPECIAL_CHARACTERS", InputSpecialCharacters, "Special Characters", "")
|
||||
DefNode(FunctionNode, FN_NODE_INPUT_STRING, def_fn_input_string, "INPUT_STRING", InputString, "String", "")
|
||||
DefNode(FunctionNode, FN_NODE_INPUT_VECTOR, def_fn_input_vector, "INPUT_VECTOR", InputVector, "Vector", "")
|
||||
DefNode(FunctionNode, FN_NODE_MATRIX_MATH, def_fn_matrix_math, "MATRIX_MATH", MatrixMath, "Matrix Math", "")
|
||||
DefNode(FunctionNode, FN_NODE_MATRIX_TRANSFORM, def_fn_matrix_transform, "MATRIX_TRANSFORM", MatrixTransform, "Matrix Transform", "")
|
||||
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_MATRIX, 0, "ROTATE_MATRIX", RotateMatrix, "Rotate Matrix", "")
|
||||
DefNode(FunctionNode, FN_NODE_SCALE_MATRIX, 0, "SCALE_MATRIX", ScaleMatrix, "Scale Matrix", "")
|
||||
DefNode(FunctionNode, FN_NODE_SEPARATE_COLOR, def_fn_combsep_color, "SEPARATE_COLOR", SeparateColor, "Separate Color", "")
|
||||
DefNode(FunctionNode, FN_NODE_SEPARATE_MATRIX, def_fn_combsep_matrix, "SEPARATE_MATRIX", SeparateMatrix, "Separate Matrix", "")
|
||||
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_TRANSLATE_MATRIX, 0, "TRANSLATE_MATRIX", TranslateMatrix, "Translate Matrix", "")
|
||||
DefNode(FunctionNode, FN_NODE_VALUE_TO_STRING, 0, "VALUE_TO_STRING", ValueToString, "Value to String", "")
|
||||
|
||||
DefNode(GeometryNode, GEO_NODE_ACCUMULATE_FIELD, def_geo_accumulate_field, "ACCUMULATE_FIELD", AccumulateField, "Accumulate Field", "Add the values of an evaluated field together and output the running total for each element")
|
||||
|
|
|
@ -23,20 +23,29 @@ set(SRC
|
|||
nodes/node_fn_align_euler_to_vector.cc
|
||||
nodes/node_fn_boolean_math.cc
|
||||
nodes/node_fn_combine_color.cc
|
||||
nodes/node_fn_combine_matrix.cc
|
||||
nodes/node_fn_compare.cc
|
||||
nodes/node_fn_decompose_matrix.cc
|
||||
nodes/node_fn_float_to_int.cc
|
||||
nodes/node_fn_input_bool.cc
|
||||
nodes/node_fn_input_color.cc
|
||||
nodes/node_fn_input_int.cc
|
||||
nodes/node_fn_input_matrix.cc
|
||||
nodes/node_fn_input_special_characters.cc
|
||||
nodes/node_fn_input_string.cc
|
||||
nodes/node_fn_input_vector.cc
|
||||
nodes/node_fn_matrix_math.cc
|
||||
nodes/node_fn_matrix_transform.cc
|
||||
nodes/node_fn_random_value.cc
|
||||
nodes/node_fn_replace_string.cc
|
||||
nodes/node_fn_rotate_euler.cc
|
||||
nodes/node_fn_rotate_matrix.cc
|
||||
nodes/node_fn_scale_matrix.cc
|
||||
nodes/node_fn_separate_color.cc
|
||||
nodes/node_fn_separate_matrix.cc
|
||||
nodes/node_fn_slice_string.cc
|
||||
nodes/node_fn_string_length.cc
|
||||
nodes/node_fn_translate_matrix.cc
|
||||
nodes/node_fn_value_to_string.cc
|
||||
|
||||
node_function_register.cc
|
||||
|
|
|
@ -9,19 +9,28 @@ void register_function_nodes()
|
|||
register_node_type_fn_align_euler_to_vector();
|
||||
register_node_type_fn_boolean_math();
|
||||
register_node_type_fn_combine_color();
|
||||
register_node_type_fn_combine_matrix();
|
||||
register_node_type_fn_compare();
|
||||
register_node_type_fn_decompose_matrix();
|
||||
register_node_type_fn_float_to_int();
|
||||
register_node_type_fn_input_bool();
|
||||
register_node_type_fn_input_color();
|
||||
register_node_type_fn_input_int();
|
||||
register_node_type_fn_input_matrix();
|
||||
register_node_type_fn_input_special_characters();
|
||||
register_node_type_fn_input_string();
|
||||
register_node_type_fn_input_vector();
|
||||
register_node_type_fn_matrix_math();
|
||||
register_node_type_fn_matrix_transform();
|
||||
register_node_type_fn_random_value();
|
||||
register_node_type_fn_replace_string();
|
||||
register_node_type_fn_rotate_euler();
|
||||
register_node_type_fn_rotate_matrix();
|
||||
register_node_type_fn_scale_matrix();
|
||||
register_node_type_fn_separate_color();
|
||||
register_node_type_fn_separate_matrix();
|
||||
register_node_type_fn_slice_string();
|
||||
register_node_type_fn_string_length();
|
||||
register_node_type_fn_translate_matrix();
|
||||
register_node_type_fn_value_to_string();
|
||||
}
|
||||
|
|
|
@ -5,18 +5,27 @@
|
|||
void register_node_type_fn_align_euler_to_vector();
|
||||
void register_node_type_fn_boolean_math();
|
||||
void register_node_type_fn_combine_color();
|
||||
void register_node_type_fn_combine_matrix();
|
||||
void register_node_type_fn_compare();
|
||||
void register_node_type_fn_decompose_matrix();
|
||||
void register_node_type_fn_float_to_int();
|
||||
void register_node_type_fn_input_bool();
|
||||
void register_node_type_fn_input_color();
|
||||
void register_node_type_fn_input_int();
|
||||
void register_node_type_fn_input_matrix();
|
||||
void register_node_type_fn_input_special_characters();
|
||||
void register_node_type_fn_input_string();
|
||||
void register_node_type_fn_input_vector();
|
||||
void register_node_type_fn_matrix_math();
|
||||
void register_node_type_fn_matrix_transform();
|
||||
void register_node_type_fn_random_value();
|
||||
void register_node_type_fn_replace_string();
|
||||
void register_node_type_fn_rotate_euler();
|
||||
void register_node_type_fn_rotate_matrix();
|
||||
void register_node_type_fn_scale_matrix();
|
||||
void register_node_type_fn_separate_color();
|
||||
void register_node_type_fn_separate_matrix();
|
||||
void register_node_type_fn_slice_string();
|
||||
void register_node_type_fn_string_length();
|
||||
void register_node_type_fn_translate_matrix();
|
||||
void register_node_type_fn_value_to_string();
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
namespace blender::nodes::node_fn_combine_matrix_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Vector>(N_("Vec0")).default_value({1.0f, 0.0f, 0.0f});
|
||||
b.add_input<decl::Vector>(N_("Vec1")).default_value({0.0f, 1.0f, 0.0f});
|
||||
b.add_input<decl::Vector>(N_("Vec2")).default_value({0.0f, 0.0f, 1.0f});
|
||||
b.add_input<decl::Vector>(N_("Vec3")).default_value({0.0f, 0.0f, 0.0f});
|
||||
b.add_input<decl::Float>(N_("Row 0 Col 0")).default_value(1.0f);
|
||||
b.add_input<decl::Float>(N_("Row 1 Col 0")).default_value(0.0f);
|
||||
b.add_input<decl::Float>(N_("Row 2 Col 0")).default_value(0.0f);
|
||||
b.add_input<decl::Float>(N_("Row 3 Col 0")).default_value(0.0f);
|
||||
b.add_input<decl::Float>(N_("Row 0 Col 1")).default_value(0.0f);
|
||||
b.add_input<decl::Float>(N_("Row 1 Col 1")).default_value(1.0f);
|
||||
b.add_input<decl::Float>(N_("Row 2 Col 1")).default_value(0.0f);
|
||||
b.add_input<decl::Float>(N_("Row 3 Col 1")).default_value(0.0f);
|
||||
b.add_input<decl::Float>(N_("Row 0 Col 2")).default_value(0.0f);
|
||||
b.add_input<decl::Float>(N_("Row 1 Col 2")).default_value(0.0f);
|
||||
b.add_input<decl::Float>(N_("Row 2 Col 2")).default_value(1.0f);
|
||||
b.add_input<decl::Float>(N_("Row 3 Col 2")).default_value(0.0f);
|
||||
b.add_input<decl::Float>(N_("Row 0 Col 3")).default_value(0.0f);
|
||||
b.add_input<decl::Float>(N_("Row 1 Col 3")).default_value(0.0f);
|
||||
b.add_input<decl::Float>(N_("Row 2 Col 3")).default_value(0.0f);
|
||||
b.add_input<decl::Float>(N_("Row 3 Col 3")).default_value(1.0f);
|
||||
b.add_output<decl::Matrix>(N_("Matrix"));
|
||||
};
|
||||
|
||||
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
|
||||
}
|
||||
|
||||
static void node_update(bNodeTree *tree, bNode *node)
|
||||
{
|
||||
const NodeCombSepMatrixMode mode = (NodeCombSepMatrixMode)node->custom1;
|
||||
|
||||
const IndexRange vector_sockets(0, 4);
|
||||
const IndexRange scalar_sockets(4, 16);
|
||||
const bool show_vector_sockets = ELEM(
|
||||
mode, NODE_COMBSEP_MATRIX_COLUMNS, NODE_COMBSEP_MATRIX_ROWS);
|
||||
const bool show_scalar_sockets = ELEM(mode, NODE_COMBSEP_MATRIX_ELEMENTS);
|
||||
|
||||
for (const int i : vector_sockets) {
|
||||
nodeSetSocketAvailability(
|
||||
tree, (bNodeSocket *)BLI_findlink(&node->inputs, i), show_vector_sockets);
|
||||
}
|
||||
for (const int i : scalar_sockets) {
|
||||
nodeSetSocketAvailability(
|
||||
tree, (bNodeSocket *)BLI_findlink(&node->inputs, i), show_scalar_sockets);
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case NODE_COMBSEP_MATRIX_COLUMNS:
|
||||
node_sock_label((bNodeSocket *)BLI_findlink(&node->inputs, vector_sockets[0]), "Column 0");
|
||||
node_sock_label((bNodeSocket *)BLI_findlink(&node->inputs, vector_sockets[1]), "Column 1");
|
||||
node_sock_label((bNodeSocket *)BLI_findlink(&node->inputs, vector_sockets[2]), "Column 2");
|
||||
node_sock_label((bNodeSocket *)BLI_findlink(&node->inputs, vector_sockets[3]), "Column 3");
|
||||
break;
|
||||
case NODE_COMBSEP_MATRIX_ROWS:
|
||||
node_sock_label((bNodeSocket *)BLI_findlink(&node->inputs, vector_sockets[0]), "Row 0");
|
||||
node_sock_label((bNodeSocket *)BLI_findlink(&node->inputs, vector_sockets[1]), "Row 1");
|
||||
node_sock_label((bNodeSocket *)BLI_findlink(&node->inputs, vector_sockets[2]), "Row 2");
|
||||
node_sock_label((bNodeSocket *)BLI_findlink(&node->inputs, vector_sockets[3]), "Row 3");
|
||||
break;
|
||||
case NODE_COMBSEP_MATRIX_ELEMENTS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void node_init(bNodeTree * /*tree*/, bNode *node)
|
||||
{
|
||||
node->custom1 = NODE_COMBSEP_MATRIX_COLUMNS;
|
||||
}
|
||||
|
||||
static const mf::MultiFunction *get_multi_function(const bNode &bnode)
|
||||
{
|
||||
const NodeCombSepMatrixMode mode = (NodeCombSepMatrixMode)bnode.custom1;
|
||||
|
||||
static auto columns_fn = mf::build::SI4_SO<float3, float3, float3, float3, float4x4>(
|
||||
"columns_to_matrix",
|
||||
[](const float3 &c0, const float3 &c1, const float3 &c2, const float3 &c3) {
|
||||
float4x4 m;
|
||||
m.view()[0] = float4(c0, 0.0f);
|
||||
m.view()[1] = float4(c1, 0.0f);
|
||||
m.view()[2] = float4(c2, 0.0f);
|
||||
m.view()[3] = float4(c3, 1.0f);
|
||||
return m;
|
||||
});
|
||||
static auto rows_fn = mf::build::SI4_SO<float3, float3, float3, float3, float4x4>(
|
||||
"rows_to_matrix",
|
||||
[](const float3 &r0, const float3 &r1, const float3 &r2, const float3 &r3) {
|
||||
float4x4 m;
|
||||
m[0][0] = r0[0];
|
||||
m[0][1] = r1[0];
|
||||
m[0][2] = r2[0];
|
||||
m[0][3] = r3[0];
|
||||
m[1][0] = r0[1];
|
||||
m[1][1] = r1[1];
|
||||
m[1][2] = r2[1];
|
||||
m[1][3] = r3[1];
|
||||
m[2][0] = r0[2];
|
||||
m[2][1] = r1[2];
|
||||
m[2][2] = r2[2];
|
||||
m[2][3] = r3[2];
|
||||
m[3][0] = 0.0f;
|
||||
m[3][1] = 0.0f;
|
||||
m[3][2] = 0.0f;
|
||||
m[3][3] = 1.0f;
|
||||
return m;
|
||||
});
|
||||
static auto exec_preset = mf::build::exec_presets::AllSpanOrSingle();
|
||||
static auto elements_fn =
|
||||
mf::build::detail::build_multi_function_with_n_inputs_one_output<float4x4>(
|
||||
"elements_to_matrix",
|
||||
[](float m00,
|
||||
float m01,
|
||||
float m02,
|
||||
float m03,
|
||||
float m10,
|
||||
float m11,
|
||||
float m12,
|
||||
float m13,
|
||||
float m20,
|
||||
float m21,
|
||||
float m22,
|
||||
float m23,
|
||||
float m30,
|
||||
float m31,
|
||||
float m32,
|
||||
float m33) {
|
||||
const float elements[] = {
|
||||
m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33};
|
||||
return float4x4(elements);
|
||||
},
|
||||
exec_preset,
|
||||
TypeSequence<float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float>());
|
||||
|
||||
switch (mode) {
|
||||
case NODE_COMBSEP_MATRIX_COLUMNS:
|
||||
return &columns_fn;
|
||||
case NODE_COMBSEP_MATRIX_ROWS:
|
||||
return &rows_fn;
|
||||
case NODE_COMBSEP_MATRIX_ELEMENTS:
|
||||
return &elements_fn;
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
const mf::MultiFunction *fn = get_multi_function(builder.node());
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_fn_combine_matrix_cc
|
||||
|
||||
void register_node_type_fn_combine_matrix(void)
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_fn_combine_matrix_cc;
|
||||
|
||||
static bNodeType ntype;
|
||||
|
||||
fn_node_type_base(&ntype, FN_NODE_COMBINE_MATRIX, "Combine Matrix", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = file_ns::node_declare;
|
||||
ntype.updatefunc = file_ns::node_update;
|
||||
ntype.initfunc = file_ns::node_init;
|
||||
ntype.build_multi_function = file_ns::node_build_multi_function;
|
||||
ntype.draw_buttons = file_ns::node_layout;
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
#include "BLI_math_matrix.h"
|
||||
#include "BLI_math_rotation.h"
|
||||
#include "BLI_math_vector.h"
|
||||
|
||||
namespace blender::nodes::node_fn_decompose_matrix_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Matrix>(N_("Matrix"));
|
||||
b.add_output<decl::Vector>(N_("Translation"));
|
||||
b.add_output<decl::Vector>(N_("Rotation"));
|
||||
b.add_output<decl::Vector>(N_("Scale"));
|
||||
};
|
||||
|
||||
class DecomposeMatrixFunction : public mf::MultiFunction {
|
||||
public:
|
||||
DecomposeMatrixFunction()
|
||||
{
|
||||
static const mf::Signature signature = []() {
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Separate Matrix 3x3", signature};
|
||||
builder.single_input<float4x4>("Matrix");
|
||||
builder.single_output<float3>("Translation");
|
||||
builder.single_output<float3>("Rotation");
|
||||
builder.single_output<float3>("Scale");
|
||||
return signature;
|
||||
}();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
void call(IndexMask mask, mf::Params params, mf::Context /*context*/) const override
|
||||
{
|
||||
const VArray<float4x4> &matrices = params.readonly_single_input<float4x4>(0, "Matrix");
|
||||
MutableSpan<float3> translations = params.uninitialized_single_output<float3>(1, "Translation");
|
||||
MutableSpan<float3> rotations = params.uninitialized_single_output<float3>(2, "Rotation");
|
||||
MutableSpan<float3> scales = params.uninitialized_single_output<float3>(3, "Scale");
|
||||
|
||||
for (int64_t i : mask) {
|
||||
const float4x4 &mat = matrices[i];
|
||||
copy_v3_v3(translations[i], mat[3]);
|
||||
mat4_to_eul(rotations[i], mat.ptr());
|
||||
mat4_to_size(scales[i], mat.ptr());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static DecomposeMatrixFunction decompose_matrix_fn;
|
||||
builder.set_matching_fn(&decompose_matrix_fn);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_fn_decompose_matrix_cc
|
||||
|
||||
void register_node_type_fn_decompose_matrix(void)
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_fn_decompose_matrix_cc;
|
||||
|
||||
static bNodeType ntype;
|
||||
|
||||
fn_node_type_base(&ntype, FN_NODE_DECOMPOSE_MATRIX, "Decompose Matrix", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = file_ns::node_declare;
|
||||
ntype.build_multi_function = file_ns::node_build_multi_function;
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
#include "BLI_math_matrix.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
namespace blender::nodes::node_fn_input_matrix_cc {
|
||||
|
||||
NODE_STORAGE_FUNCS(NodeInputMatrix);
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_output<decl::Matrix>(N_("Matrix"));
|
||||
};
|
||||
|
||||
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
uiItemR(layout, ptr, "matrix", 0, "", ICON_NONE);
|
||||
}
|
||||
|
||||
static void node_init(bNodeTree * /*tree*/, bNode *node)
|
||||
{
|
||||
NodeInputMatrix *data = MEM_new<NodeInputMatrix>(__func__);
|
||||
unit_m4(data->matrix);
|
||||
node->storage = data;
|
||||
}
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
const NodeInputMatrix &storage = node_storage(builder.node());
|
||||
builder.construct_and_set_matching_fn<mf::CustomMF_Constant<float4x4>>(float4x4{storage.matrix});
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_fn_input_matrix_cc
|
||||
|
||||
void register_node_type_fn_input_matrix(void)
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_fn_input_matrix_cc;
|
||||
|
||||
static bNodeType ntype;
|
||||
|
||||
fn_node_type_base(&ntype, FN_NODE_INPUT_MATRIX, "Matrix", NODE_CLASS_INPUT);
|
||||
node_type_storage(
|
||||
&ntype, "NodeInputMatrix", node_free_standard_storage, node_copy_standard_storage);
|
||||
ntype.declare = file_ns::node_declare;
|
||||
ntype.initfunc = file_ns::node_init;
|
||||
ntype.build_multi_function = file_ns::node_build_multi_function;
|
||||
ntype.draw_buttons = file_ns::node_layout;
|
||||
/* Matrix columns need more horizontal space */
|
||||
node_type_size_preset(&ntype, NODE_SIZE_LARGE);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
|
||||
#include "NOD_socket_search_link.hh"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
namespace blender::nodes::node_fn_matrix_math_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Matrix>(N_("Matrix"));
|
||||
b.add_input<decl::Matrix>(N_("Matrix"), "Matrix_001");
|
||||
b.add_input<decl::Float>(N_("Scale")).default_value(1.0f);
|
||||
b.add_output<decl::Matrix>(N_("Matrix"));
|
||||
b.add_output<decl::Float>(N_("Value"));
|
||||
};
|
||||
|
||||
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
uiItemR(layout, ptr, "operation", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
}
|
||||
|
||||
static void node_update(bNodeTree *tree, bNode *node)
|
||||
{
|
||||
const NodeMatrixMathOperation op = (NodeMatrixMathOperation)node->custom1;
|
||||
|
||||
bNodeSocket *in_matrix_a = (bNodeSocket *)BLI_findlink(&node->inputs, 0);
|
||||
bNodeSocket *in_matrix_b = (bNodeSocket *)BLI_findlink(&node->inputs, 1);
|
||||
bNodeSocket *in_scale = (bNodeSocket *)BLI_findlink(&node->inputs, 2);
|
||||
bNodeSocket *out_matrix = (bNodeSocket *)BLI_findlink(&node->outputs, 0);
|
||||
bNodeSocket *out_value = (bNodeSocket *)BLI_findlink(&node->outputs, 1);
|
||||
|
||||
nodeSetSocketAvailability(tree, in_matrix_a, true);
|
||||
nodeSetSocketAvailability(
|
||||
tree,
|
||||
in_matrix_b,
|
||||
ELEM(op, NODE_MATRIX_MATH_ADD, NODE_MATRIX_MATH_SUBTRACT, NODE_MATRIX_MATH_MULTIPLY));
|
||||
nodeSetSocketAvailability(tree, in_scale, ELEM(op, NODE_MATRIX_MATH_SCALAR_MULTIPLY));
|
||||
|
||||
nodeSetSocketAvailability(tree,
|
||||
out_matrix,
|
||||
ELEM(op,
|
||||
NODE_MATRIX_MATH_ADD,
|
||||
NODE_MATRIX_MATH_SUBTRACT,
|
||||
NODE_MATRIX_MATH_SCALAR_MULTIPLY,
|
||||
NODE_MATRIX_MATH_MULTIPLY,
|
||||
NODE_MATRIX_MATH_TRANSPOSE,
|
||||
NODE_MATRIX_MATH_INVERSE));
|
||||
nodeSetSocketAvailability(
|
||||
tree, out_value, ELEM(op, NODE_MATRIX_MATH_DETERMINANT, NODE_MATRIX_MATH_TRACE));
|
||||
|
||||
/* Labels */
|
||||
node_sock_label_clear(in_matrix_a);
|
||||
node_sock_label_clear(in_matrix_b);
|
||||
node_sock_label_clear(in_scale);
|
||||
}
|
||||
|
||||
static void node_init(bNodeTree * /*tree*/, bNode *node)
|
||||
{
|
||||
node->custom1 = NODE_MATRIX_MATH_ADD;
|
||||
}
|
||||
|
||||
static const mf::MultiFunction *get_multi_function(NodeMatrixMathOperation op)
|
||||
{
|
||||
static auto exec_preset = mf::build::exec_presets::AllSpanOrSingle();
|
||||
|
||||
switch (op) {
|
||||
case NODE_MATRIX_MATH_ADD: {
|
||||
static auto fn = mf::build::SI2_SO<float4x4, float4x4, float4x4>(
|
||||
"add",
|
||||
[](const float4x4 &a, const float4x4 &b) -> float4x4 { return a + b; },
|
||||
exec_preset);
|
||||
return &fn;
|
||||
}
|
||||
case NODE_MATRIX_MATH_SUBTRACT: {
|
||||
static auto fn = mf::build::SI2_SO<float4x4, float4x4, float4x4>(
|
||||
"subtract",
|
||||
[](const float4x4 &a, const float4x4 &b) -> float4x4 { return a - b; },
|
||||
exec_preset);
|
||||
return &fn;
|
||||
}
|
||||
case NODE_MATRIX_MATH_SCALAR_MULTIPLY: {
|
||||
static auto fn = mf::build::SI2_SO<float4x4, float, float4x4>(
|
||||
"scalar_multiply",
|
||||
[](const float4x4 &a, const float &s) -> float4x4 { return a * s; },
|
||||
exec_preset);
|
||||
return &fn;
|
||||
}
|
||||
case NODE_MATRIX_MATH_MULTIPLY: {
|
||||
static auto fn = mf::build::SI2_SO<float4x4, float4x4, float4x4>(
|
||||
"multiply",
|
||||
[](const float4x4 &a, const float4x4 &b) -> float4x4 { return a * b; },
|
||||
exec_preset);
|
||||
return &fn;
|
||||
}
|
||||
case NODE_MATRIX_MATH_TRANSPOSE: {
|
||||
static auto fn = mf::build::SI1_SO<float4x4, float4x4>(
|
||||
"transpose",
|
||||
[](const float4x4 &a) -> float4x4 { return math::transpose(a); },
|
||||
exec_preset);
|
||||
return &fn;
|
||||
}
|
||||
case NODE_MATRIX_MATH_INVERSE: {
|
||||
static auto fn = mf::build::SI1_SO<float4x4, float4x4>(
|
||||
"inverse",
|
||||
[](const float4x4 &a) -> float4x4 { return math::invert(a); },
|
||||
exec_preset);
|
||||
return &fn;
|
||||
}
|
||||
case NODE_MATRIX_MATH_DETERMINANT: {
|
||||
static auto fn = mf::build::SI1_SO<float4x4, float>(
|
||||
"determinant",
|
||||
[](const float4x4 &a) -> float { return math::determinant(a); },
|
||||
exec_preset);
|
||||
return &fn;
|
||||
}
|
||||
case NODE_MATRIX_MATH_TRACE: {
|
||||
static auto fn = mf::build::SI1_SO<float4x4, float>(
|
||||
"trace",
|
||||
[](const float4x4 &a) -> float { return a[0][0] + a[1][1] + a[2][2] + a[3][3]; },
|
||||
exec_preset);
|
||||
return &fn;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
const NodeMatrixMathOperation op = (NodeMatrixMathOperation)builder.node().custom1;
|
||||
const mf::MultiFunction *fn = get_multi_function(op);
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_fn_matrix_math_cc
|
||||
|
||||
void register_node_type_fn_matrix_math(void)
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_fn_matrix_math_cc;
|
||||
|
||||
static bNodeType ntype;
|
||||
|
||||
fn_node_type_base(&ntype, FN_NODE_MATRIX_MATH, "Matrix Math", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = file_ns::node_declare;
|
||||
ntype.updatefunc = file_ns::node_update;
|
||||
ntype.initfunc = file_ns::node_init;
|
||||
ntype.build_multi_function = file_ns::node_build_multi_function;
|
||||
ntype.draw_buttons = file_ns::node_layout;
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
namespace blender::nodes::node_fn_matrix_transform_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Matrix>(N_("Matrix"));
|
||||
b.add_input<decl::Vector>(N_("Vector"));
|
||||
b.add_output<decl::Vector>(N_("Vector"));
|
||||
};
|
||||
|
||||
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
uiItemR(layout, ptr, "vector_mode", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
}
|
||||
|
||||
static void node_init(bNodeTree * /*tree*/, bNode *node)
|
||||
{
|
||||
node->custom1 = NODE_MATRIX_TRANSFORM_POINT;
|
||||
}
|
||||
|
||||
static const mf::MultiFunction *get_multi_function(NodeMatrixTransformVectorMode vector_mode)
|
||||
{
|
||||
static auto exec_preset = mf::build::exec_presets::AllSpanOrSingle();
|
||||
|
||||
switch (vector_mode) {
|
||||
case NODE_MATRIX_TRANSFORM_POINT: {
|
||||
static auto fn = mf::build::SI2_SO<float4x4, float3, float3>(
|
||||
"transform_point",
|
||||
[](const float4x4 &m, const float3 &v) -> float3 { return math::transform_point(m, v); },
|
||||
exec_preset);
|
||||
return &fn;
|
||||
}
|
||||
case NODE_MATRIX_TRANSFORM_DIRECTION: {
|
||||
static auto fn = mf::build::SI2_SO<float4x4, float3, float3>(
|
||||
"transform_direction",
|
||||
[](const float4x4 &m, const float3 &v) -> float3 { return math::transform_direction(m, v); },
|
||||
exec_preset);
|
||||
return &fn;
|
||||
}
|
||||
case NODE_MATRIX_TRANSFORM_NORMAL: {
|
||||
static auto fn = mf::build::SI2_SO<float4x4, float3, float3>(
|
||||
"transform_normal",
|
||||
[](const float4x4 &m, const float3 &v) -> float3 {
|
||||
const float3x3 transpose_inverse = math::transpose(
|
||||
math::invert(float3x3(m.view<3, 3>())));
|
||||
return math::transform_direction(transpose_inverse, v);
|
||||
},
|
||||
exec_preset);
|
||||
return &fn;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
const NodeMatrixTransformVectorMode vector_mode = (NodeMatrixTransformVectorMode)builder.node().custom1;
|
||||
const mf::MultiFunction *fn = get_multi_function(vector_mode);
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_fn_matrix_transform_cc
|
||||
|
||||
void register_node_type_fn_matrix_transform(void)
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_fn_matrix_transform_cc;
|
||||
|
||||
static bNodeType ntype;
|
||||
|
||||
fn_node_type_base(&ntype, FN_NODE_MATRIX_TRANSFORM, "Matrix Transform", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = file_ns::node_declare;
|
||||
ntype.initfunc = file_ns::node_init;
|
||||
ntype.draw_buttons = file_ns::node_layout;
|
||||
ntype.build_multi_function = file_ns::node_build_multi_function;
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
#include "BLI_math_rotation.h"
|
||||
|
||||
namespace blender::nodes::node_fn_rotate_matrix_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Matrix>(N_("Matrix"));
|
||||
b.add_input<decl::Vector>(N_("Rotation"));
|
||||
b.add_output<decl::Matrix>(N_("Matrix"));
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI2_SO<float4x4, float3, float4x4>(
|
||||
"rotate_matrix", [](const float4x4 &mat, const float3 &rot) {
|
||||
float4x4 rot_mat;
|
||||
eulO_to_mat4(rot_mat.ptr(), rot, EULER_ORDER_DEFAULT);
|
||||
return rot_mat * mat;
|
||||
});
|
||||
builder.set_matching_fn(&fn);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_fn_rotate_matrix_cc
|
||||
|
||||
void register_node_type_fn_rotate_matrix(void)
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_fn_rotate_matrix_cc;
|
||||
|
||||
static bNodeType ntype;
|
||||
|
||||
fn_node_type_base(&ntype, FN_NODE_ROTATE_MATRIX, "Rotate Matrix", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = file_ns::node_declare;
|
||||
ntype.build_multi_function = file_ns::node_build_multi_function;
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
#include "BLI_math_vector.h"
|
||||
|
||||
namespace blender::nodes::node_fn_scale_matrix_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Matrix>(N_("Matrix"));
|
||||
b.add_input<decl::Vector>(N_("Scale"));
|
||||
b.add_output<decl::Matrix>(N_("Matrix"));
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI2_SO<float4x4, float3, float4x4>(
|
||||
"scale_matrix", [](const float4x4 &mat, const float3 &scale) {
|
||||
float4x4 result;
|
||||
mul_v3_v3fl(result.view()[0], mat[0], scale[0]);
|
||||
mul_v3_v3fl(result.view()[1], mat[1], scale[1]);
|
||||
mul_v3_v3fl(result.view()[2], mat[2], scale[2]);
|
||||
return result;
|
||||
});
|
||||
builder.set_matching_fn(&fn);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_fn_scale_matrix_cc
|
||||
|
||||
void register_node_type_fn_scale_matrix(void)
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_fn_scale_matrix_cc;
|
||||
|
||||
static bNodeType ntype;
|
||||
|
||||
fn_node_type_base(&ntype, FN_NODE_SCALE_MATRIX, "Scale Matrix", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = file_ns::node_declare;
|
||||
ntype.build_multi_function = file_ns::node_build_multi_function;
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
|
@ -0,0 +1,267 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
namespace blender::nodes::node_fn_separate_matrix_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Matrix>(N_("Matrix")).default_value(float4x4::identity());
|
||||
b.add_output<decl::Vector>(N_("Vec0"));
|
||||
b.add_output<decl::Vector>(N_("Vec1"));
|
||||
b.add_output<decl::Vector>(N_("Vec2"));
|
||||
b.add_output<decl::Vector>(N_("Vec3"));
|
||||
b.add_output<decl::Float>(N_("Row 0 Col 0"));
|
||||
b.add_output<decl::Float>(N_("Row 1 Col 0"));
|
||||
b.add_output<decl::Float>(N_("Row 2 Col 0"));
|
||||
b.add_output<decl::Float>(N_("Row 3 Col 0"));
|
||||
b.add_output<decl::Float>(N_("Row 0 Col 1"));
|
||||
b.add_output<decl::Float>(N_("Row 1 Col 1"));
|
||||
b.add_output<decl::Float>(N_("Row 2 Col 1"));
|
||||
b.add_output<decl::Float>(N_("Row 3 Col 1"));
|
||||
b.add_output<decl::Float>(N_("Row 0 Col 2"));
|
||||
b.add_output<decl::Float>(N_("Row 1 Col 2"));
|
||||
b.add_output<decl::Float>(N_("Row 2 Col 2"));
|
||||
b.add_output<decl::Float>(N_("Row 3 Col 2"));
|
||||
b.add_output<decl::Float>(N_("Row 0 Col 3"));
|
||||
b.add_output<decl::Float>(N_("Row 1 Col 3"));
|
||||
b.add_output<decl::Float>(N_("Row 2 Col 3"));
|
||||
b.add_output<decl::Float>(N_("Row 3 Col 3"));
|
||||
};
|
||||
|
||||
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
|
||||
}
|
||||
|
||||
static void node_update(bNodeTree *tree, bNode *node)
|
||||
{
|
||||
const NodeCombSepMatrixMode mode = (NodeCombSepMatrixMode)node->custom1;
|
||||
|
||||
const IndexRange vector_sockets(0, 4);
|
||||
const IndexRange scalar_sockets(4, 16);
|
||||
const bool show_vector_sockets = ELEM(
|
||||
mode, NODE_COMBSEP_MATRIX_COLUMNS, NODE_COMBSEP_MATRIX_ROWS);
|
||||
const bool show_scalar_sockets = ELEM(mode, NODE_COMBSEP_MATRIX_ELEMENTS);
|
||||
|
||||
for (const int i : vector_sockets) {
|
||||
nodeSetSocketAvailability(
|
||||
tree, (bNodeSocket *)BLI_findlink(&node->outputs, i), show_vector_sockets);
|
||||
}
|
||||
for (const int i : scalar_sockets) {
|
||||
nodeSetSocketAvailability(
|
||||
tree, (bNodeSocket *)BLI_findlink(&node->outputs, i), show_scalar_sockets);
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case NODE_COMBSEP_MATRIX_COLUMNS:
|
||||
node_sock_label((bNodeSocket *)BLI_findlink(&node->outputs, vector_sockets[0]), "Column 0");
|
||||
node_sock_label((bNodeSocket *)BLI_findlink(&node->outputs, vector_sockets[1]), "Column 1");
|
||||
node_sock_label((bNodeSocket *)BLI_findlink(&node->outputs, vector_sockets[2]), "Column 2");
|
||||
node_sock_label((bNodeSocket *)BLI_findlink(&node->outputs, vector_sockets[3]), "Column 3");
|
||||
break;
|
||||
case NODE_COMBSEP_MATRIX_ROWS:
|
||||
node_sock_label((bNodeSocket *)BLI_findlink(&node->outputs, vector_sockets[0]), "Row 0");
|
||||
node_sock_label((bNodeSocket *)BLI_findlink(&node->outputs, vector_sockets[1]), "Row 1");
|
||||
node_sock_label((bNodeSocket *)BLI_findlink(&node->outputs, vector_sockets[2]), "Row 2");
|
||||
node_sock_label((bNodeSocket *)BLI_findlink(&node->outputs, vector_sockets[3]), "Row 3");
|
||||
break;
|
||||
case NODE_COMBSEP_MATRIX_ELEMENTS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void node_init(bNodeTree * /*tree*/, bNode *node)
|
||||
{
|
||||
node->custom1 = NODE_COMBSEP_MATRIX_COLUMNS;
|
||||
}
|
||||
|
||||
class SeparateColumnsFunction : public mf::MultiFunction {
|
||||
public:
|
||||
SeparateColumnsFunction()
|
||||
{
|
||||
static const mf::Signature signature = []() {
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Separate Matrix 4x4", signature};
|
||||
builder.single_input<float4x4>("Matrix");
|
||||
builder.single_output<float3>("Column0");
|
||||
builder.single_output<float3>("Column1");
|
||||
builder.single_output<float3>("Column2");
|
||||
builder.single_output<float3>("Column3");
|
||||
return signature;
|
||||
}();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
void call(IndexMask mask, mf::Params params, mf::Context /*context*/) const override
|
||||
{
|
||||
const VArray<float4x4> &matrices = params.readonly_single_input<float4x4>(0, "Matrix");
|
||||
MutableSpan<float3> col0 = params.uninitialized_single_output<float3>(1, "Column0");
|
||||
MutableSpan<float3> col1 = params.uninitialized_single_output<float3>(2, "Column1");
|
||||
MutableSpan<float3> col2 = params.uninitialized_single_output<float3>(3, "Column2");
|
||||
MutableSpan<float3> col3 = params.uninitialized_single_output<float3>(4, "Column3");
|
||||
|
||||
for (int64_t i : mask) {
|
||||
const float4x4 &mat = matrices[i];
|
||||
col0[i] = float3(mat[0]);
|
||||
col1[i] = float3(mat[1]);
|
||||
col2[i] = float3(mat[2]);
|
||||
col3[i] = float3(mat[3]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SeparateRowsFunction : public mf::MultiFunction {
|
||||
public:
|
||||
SeparateRowsFunction()
|
||||
{
|
||||
static const mf::Signature signature = []() {
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Separate Matrix 4x4", signature};
|
||||
builder.single_input<float4x4>("Matrix");
|
||||
builder.single_output<float3>("Row0");
|
||||
builder.single_output<float3>("Row1");
|
||||
builder.single_output<float3>("Row2");
|
||||
builder.single_output<float3>("Row3");
|
||||
return signature;
|
||||
}();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
void call(IndexMask mask, mf::Params params, mf::Context /*context*/) const override
|
||||
{
|
||||
const VArray<float4x4> &matrices = params.readonly_single_input<float4x4>(0, "Matrix");
|
||||
MutableSpan<float3> row0 = params.uninitialized_single_output<float3>(1, "Row0");
|
||||
MutableSpan<float3> row1 = params.uninitialized_single_output<float3>(2, "Row1");
|
||||
MutableSpan<float3> row2 = params.uninitialized_single_output<float3>(3, "Row2");
|
||||
MutableSpan<float3> row3 = params.uninitialized_single_output<float3>(4, "Row3");
|
||||
|
||||
for (int64_t i : mask) {
|
||||
const float4x4 &mat = matrices[i];
|
||||
row0[i] = float3(mat[0][0], mat[1][0], mat[2][0]);
|
||||
row1[i] = float3(mat[0][1], mat[1][1], mat[2][1]);
|
||||
row2[i] = float3(mat[0][2], mat[1][2], mat[2][2]);
|
||||
row3[i] = float3(mat[0][3], mat[1][3], mat[2][3]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SeparateElementsFunction : public mf::MultiFunction {
|
||||
public:
|
||||
SeparateElementsFunction()
|
||||
{
|
||||
static const mf::Signature signature = []() {
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Separate Matrix 4x4", signature};
|
||||
builder.single_input<float4x4>("Matrix");
|
||||
builder.single_output<float>("Row0Column0");
|
||||
builder.single_output<float>("Row0Column1");
|
||||
builder.single_output<float>("Row0Column2");
|
||||
builder.single_output<float>("Row0Column3");
|
||||
builder.single_output<float>("Row1Column0");
|
||||
builder.single_output<float>("Row1Column1");
|
||||
builder.single_output<float>("Row1Column2");
|
||||
builder.single_output<float>("Row1Column3");
|
||||
builder.single_output<float>("Row2Column0");
|
||||
builder.single_output<float>("Row2Column1");
|
||||
builder.single_output<float>("Row2Column2");
|
||||
builder.single_output<float>("Row2Column3");
|
||||
builder.single_output<float>("Row3Column0");
|
||||
builder.single_output<float>("Row3Column1");
|
||||
builder.single_output<float>("Row3Column2");
|
||||
builder.single_output<float>("Row3Column3");
|
||||
return signature;
|
||||
}();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
void call(IndexMask mask, mf::Params params, mf::Context /*context*/) const override
|
||||
{
|
||||
const VArray<float4x4> &matrices = params.readonly_single_input<float4x4>(0, "Matrix");
|
||||
MutableSpan<float> m00 = params.uninitialized_single_output<float>(1, "Row0Column0");
|
||||
MutableSpan<float> m10 = params.uninitialized_single_output<float>(2, "Row0Column1");
|
||||
MutableSpan<float> m20 = params.uninitialized_single_output<float>(3, "Row0Column2");
|
||||
MutableSpan<float> m30 = params.uninitialized_single_output<float>(4, "Row0Column3");
|
||||
MutableSpan<float> m01 = params.uninitialized_single_output<float>(5, "Row1Column0");
|
||||
MutableSpan<float> m11 = params.uninitialized_single_output<float>(6, "Row1Column1");
|
||||
MutableSpan<float> m21 = params.uninitialized_single_output<float>(7, "Row1Column2");
|
||||
MutableSpan<float> m31 = params.uninitialized_single_output<float>(8, "Row1Column3");
|
||||
MutableSpan<float> m02 = params.uninitialized_single_output<float>(9, "Row2Column0");
|
||||
MutableSpan<float> m12 = params.uninitialized_single_output<float>(10, "Row2Column1");
|
||||
MutableSpan<float> m22 = params.uninitialized_single_output<float>(11, "Row2Column2");
|
||||
MutableSpan<float> m32 = params.uninitialized_single_output<float>(12, "Row2Column3");
|
||||
MutableSpan<float> m03 = params.uninitialized_single_output<float>(13, "Row3Column0");
|
||||
MutableSpan<float> m13 = params.uninitialized_single_output<float>(14, "Row3Column1");
|
||||
MutableSpan<float> m23 = params.uninitialized_single_output<float>(15, "Row3Column2");
|
||||
MutableSpan<float> m33 = params.uninitialized_single_output<float>(16, "Row3Column3");
|
||||
|
||||
for (int64_t i : mask) {
|
||||
const float4x4 &mat = matrices[i];
|
||||
m00[i] = mat[0][0];
|
||||
m01[i] = mat[0][1];
|
||||
m02[i] = mat[0][2];
|
||||
m03[i] = mat[0][3];
|
||||
m10[i] = mat[1][0];
|
||||
m11[i] = mat[1][1];
|
||||
m12[i] = mat[1][2];
|
||||
m13[i] = mat[1][3];
|
||||
m20[i] = mat[2][0];
|
||||
m21[i] = mat[2][1];
|
||||
m22[i] = mat[2][2];
|
||||
m23[i] = mat[2][3];
|
||||
m30[i] = mat[3][0];
|
||||
m31[i] = mat[3][1];
|
||||
m32[i] = mat[3][2];
|
||||
m33[i] = mat[3][3];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
const NodeCombSepMatrixMode mode = (NodeCombSepMatrixMode)builder.node().custom1;
|
||||
|
||||
switch (mode) {
|
||||
case NODE_COMBSEP_MATRIX_COLUMNS: {
|
||||
static SeparateColumnsFunction fn;
|
||||
builder.set_matching_fn(fn);
|
||||
break;
|
||||
}
|
||||
case NODE_COMBSEP_MATRIX_ROWS: {
|
||||
static SeparateRowsFunction fn;
|
||||
builder.set_matching_fn(fn);
|
||||
break;
|
||||
}
|
||||
case NODE_COMBSEP_MATRIX_ELEMENTS: {
|
||||
static SeparateElementsFunction fn;
|
||||
builder.set_matching_fn(fn);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_fn_separate_matrix_cc
|
||||
|
||||
void register_node_type_fn_separate_matrix(void)
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_fn_separate_matrix_cc;
|
||||
|
||||
static bNodeType ntype;
|
||||
|
||||
fn_node_type_base(&ntype, FN_NODE_SEPARATE_MATRIX, "Separate Matrix", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = file_ns::node_declare;
|
||||
ntype.updatefunc = file_ns::node_update;
|
||||
ntype.initfunc = file_ns::node_init;
|
||||
ntype.build_multi_function = file_ns::node_build_multi_function;
|
||||
ntype.draw_buttons = file_ns::node_layout;
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_translate_matrix_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Matrix>(N_("Matrix"));
|
||||
b.add_input<decl::Vector>(N_("Translation"));
|
||||
b.add_output<decl::Matrix>(N_("Matrix"));
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI2_SO<float4x4, float3, float4x4>(
|
||||
"translate_matrix", [](const float4x4 &mat, const float3 &translation) {
|
||||
float4x4 result;
|
||||
result.view()[0] = mat.view()[0];
|
||||
result.view()[1] = mat.view()[1];
|
||||
result.view()[2] = mat.view()[2];
|
||||
result.view()[3] = mat.view()[3] + float4(translation, 0.0f);
|
||||
return result;
|
||||
});
|
||||
builder.set_matching_fn(&fn);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_fn_translate_matrix_cc
|
||||
|
||||
void register_node_type_fn_translate_matrix(void)
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_fn_translate_matrix_cc;
|
||||
|
||||
static bNodeType ntype;
|
||||
|
||||
fn_node_type_base(&ntype, FN_NODE_TRANSLATE_MATRIX, "Translate Matrix", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = file_ns::node_declare;
|
||||
ntype.build_multi_function = file_ns::node_build_multi_function;
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
|
@ -102,7 +102,8 @@ static bool geometry_node_tree_socket_type_valid(bNodeTreeType * /*treetype*/,
|
|||
SOCK_COLLECTION,
|
||||
SOCK_TEXTURE,
|
||||
SOCK_IMAGE,
|
||||
SOCK_MATERIAL);
|
||||
SOCK_MATERIAL,
|
||||
SOCK_MATRIX);
|
||||
}
|
||||
|
||||
void register_node_tree_type_geo()
|
||||
|
|
|
@ -22,6 +22,8 @@ std::optional<eCustomDataType> node_data_type_to_custom_data_type(const eNodeSoc
|
|||
return CD_PROP_FLOAT;
|
||||
case SOCK_VECTOR:
|
||||
return CD_PROP_FLOAT3;
|
||||
case SOCK_MATRIX:
|
||||
return CD_PROP_FLOAT4X4;
|
||||
case SOCK_RGBA:
|
||||
return CD_PROP_COLOR;
|
||||
case SOCK_BOOLEAN:
|
||||
|
|
|
@ -148,6 +148,11 @@ static SocketDeclarationPtr declaration_for_interface_socket(const bNodeSocket &
|
|||
dst = std::move(decl);
|
||||
break;
|
||||
}
|
||||
case SOCK_MATRIX: {
|
||||
std::unique_ptr<decl::Matrix> decl = std::make_unique<decl::Matrix>();
|
||||
dst = std::move(decl);
|
||||
break;
|
||||
}
|
||||
case SOCK_RGBA: {
|
||||
const auto &value = *io_socket.default_value_typed<bNodeSocketValueRGBA>();
|
||||
std::unique_ptr<decl::Color> decl = std::make_unique<decl::Color>();
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "BLI_color.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_matrix_types.hh"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_string.h"
|
||||
|
@ -79,6 +80,28 @@ struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree,
|
|||
dval->max = stemp->max;
|
||||
break;
|
||||
}
|
||||
case SOCK_MATRIX: {
|
||||
bNodeSocketValueMatrix *dval = (bNodeSocketValueMatrix *)sock->default_value;
|
||||
dval->value[0][0] = stemp->val1;
|
||||
dval->value[0][1] = 0.0f;
|
||||
dval->value[0][2] = 0.0f;
|
||||
dval->value[0][3] = 0.0f;
|
||||
dval->value[1][0] = 0.0f;
|
||||
dval->value[1][1] = stemp->val1;
|
||||
dval->value[1][2] = 0.0f;
|
||||
dval->value[1][3] = 0.0f;
|
||||
dval->value[2][0] = 0.0f;
|
||||
dval->value[2][1] = 0.0f;
|
||||
dval->value[2][2] = stemp->val1;
|
||||
dval->value[2][3] = 0.0f;
|
||||
dval->value[3][0] = 0.0f;
|
||||
dval->value[3][1] = 0.0f;
|
||||
dval->value[3][2] = 0.0f;
|
||||
dval->value[3][3] = stemp->val1;
|
||||
dval->min = stemp->min;
|
||||
dval->max = stemp->max;
|
||||
break;
|
||||
}
|
||||
case SOCK_RGBA: {
|
||||
bNodeSocketValueRGBA *dval = (bNodeSocketValueRGBA *)sock->default_value;
|
||||
dval->value[0] = stemp->val1;
|
||||
|
@ -351,6 +374,20 @@ void node_socket_init_default_value(bNodeSocket *sock)
|
|||
sock->default_value = dval;
|
||||
break;
|
||||
}
|
||||
case SOCK_MATRIX: {
|
||||
static float default_value[][4] = {{1.0f, 0.0f, 0.0f, 0.0f},
|
||||
{0.0f, 1.0f, 0.0f, 0.0f},
|
||||
{0.0f, 0.0f, 1.0f, 0.0f},
|
||||
{0.0f, 0.0f, 0.0f, 1.0f}};
|
||||
bNodeSocketValueMatrix *dval = MEM_cnew<bNodeSocketValueMatrix>(
|
||||
"node socket value vector");
|
||||
copy_m4_m4(dval->value, default_value);
|
||||
dval->min = -FLT_MAX;
|
||||
dval->max = FLT_MAX;
|
||||
|
||||
sock->default_value = dval;
|
||||
break;
|
||||
}
|
||||
case SOCK_RGBA: {
|
||||
static float default_value[] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
bNodeSocketValueRGBA *dval = MEM_cnew<bNodeSocketValueRGBA>("node socket value color");
|
||||
|
@ -451,6 +488,12 @@ void node_socket_copy_default_value(bNodeSocket *to, const bNodeSocket *from)
|
|||
*toval = *fromval;
|
||||
break;
|
||||
}
|
||||
case SOCK_MATRIX: {
|
||||
bNodeSocketValueMatrix *toval = (bNodeSocketValueMatrix *)to->default_value;
|
||||
bNodeSocketValueMatrix *fromval = (bNodeSocketValueMatrix *)from->default_value;
|
||||
*toval = *fromval;
|
||||
break;
|
||||
}
|
||||
case SOCK_RGBA: {
|
||||
bNodeSocketValueRGBA *toval = (bNodeSocketValueRGBA *)to->default_value;
|
||||
bNodeSocketValueRGBA *fromval = (bNodeSocketValueRGBA *)from->default_value;
|
||||
|
@ -670,6 +713,22 @@ static bNodeSocketType *make_socket_type_vector(PropertySubType subtype)
|
|||
return socktype;
|
||||
}
|
||||
|
||||
static bNodeSocketType *make_socket_type_matrix()
|
||||
{
|
||||
bNodeSocketType *socktype = make_standard_socket_type(SOCK_MATRIX, PROP_MATRIX);
|
||||
socktype->base_cpp_type = &blender::CPPType::get<blender::float4x4>();
|
||||
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
|
||||
*(blender::float4x4 *)r_value = float4x4(((bNodeSocketValueMatrix *)socket.default_value)->value);
|
||||
};
|
||||
socktype->geometry_nodes_cpp_type = &blender::CPPType::get<ValueOrField<blender::float4x4>>();
|
||||
socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) {
|
||||
blender::float4x4 value;
|
||||
socket.typeinfo->get_base_cpp_value(socket, &value);
|
||||
new (r_value) ValueOrField<blender::float4x4>(value);
|
||||
};
|
||||
return socktype;
|
||||
}
|
||||
|
||||
static bNodeSocketType *make_socket_type_rgba()
|
||||
{
|
||||
bNodeSocketType *socktype = make_standard_socket_type(SOCK_RGBA, PROP_NONE);
|
||||
|
@ -804,6 +863,8 @@ void register_standard_node_socket_types()
|
|||
nodeRegisterSocketType(make_socket_type_vector(PROP_EULER));
|
||||
nodeRegisterSocketType(make_socket_type_vector(PROP_XYZ));
|
||||
|
||||
nodeRegisterSocketType(make_socket_type_matrix());
|
||||
|
||||
nodeRegisterSocketType(make_socket_type_rgba());
|
||||
|
||||
nodeRegisterSocketType(make_socket_type_string());
|
||||
|
|
|
@ -273,6 +273,52 @@ bNodeSocket &Vector::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #Matrix
|
||||
* \{ */
|
||||
|
||||
bNodeSocket &Matrix::build(bNodeTree &ntree, bNode &node) const
|
||||
{
|
||||
bNodeSocket &socket = *nodeAddStaticSocket(
|
||||
&ntree, &node, in_out, SOCK_MATRIX, PROP_MATRIX, identifier.c_str(), name.c_str());
|
||||
this->set_common_flags(socket);
|
||||
bNodeSocketValueMatrix &value = *(bNodeSocketValueMatrix *)socket.default_value;
|
||||
copy_m4_m4(value.value, default_value_.ptr());
|
||||
value.min = soft_min_value_;
|
||||
value.max = soft_max_value_;
|
||||
return socket;
|
||||
}
|
||||
|
||||
bool Matrix::matches(const bNodeSocket &socket) const
|
||||
{
|
||||
if (!this->matches_common_data(socket)) {
|
||||
return false;
|
||||
}
|
||||
if (socket.type != SOCK_MATRIX) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Matrix::can_connect(const bNodeSocket &socket) const
|
||||
{
|
||||
return sockets_can_connect(*this, socket) && socket.type == SOCK_MATRIX;
|
||||
}
|
||||
|
||||
bNodeSocket &Matrix::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
|
||||
{
|
||||
if (socket.type != SOCK_MATRIX) {
|
||||
BLI_assert(socket.in_out == in_out);
|
||||
return this->build(ntree, node);
|
||||
}
|
||||
this->set_common_flags(socket);
|
||||
/*bNodeSocketValueMatrix &value = *(bNodeSocketValueMatrix *)socket.default_value;*/
|
||||
STRNCPY(socket.name, name.c_str());
|
||||
return socket;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #Bool
|
||||
* \{ */
|
||||
|
|
Loading…
Reference in New Issue