Geometry Nodes: Matrix socket type, attribute type, and initial nodes #116166
|
@ -533,7 +533,7 @@ class NODE_MT_category_GEO_UTILITIES(Menu):
|
|||
bl_idname = "NODE_MT_category_GEO_UTILITIES"
|
||||
bl_label = "Utilities"
|
||||
|
||||
def draw(self, _context):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.menu("NODE_MT_geometry_node_GEO_COLOR")
|
||||
layout.menu("NODE_MT_category_GEO_TEXT")
|
||||
|
@ -541,6 +541,8 @@ 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")
|
||||
if context.preferences.experimental.use_new_matrix_socket:
|
||||
layout.menu("NODE_MT_category_utilities_matrix")
|
||||
layout.menu("NODE_MT_category_GEO_UTILITIES_ROTATION")
|
||||
layout.menu("NODE_MT_category_GEO_UTILITIES_DEPRECATED")
|
||||
layout.separator()
|
||||
|
@ -592,6 +594,22 @@ class NODE_MT_category_GEO_UTILITIES_ROTATION(Menu):
|
|||
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Rotation")
|
||||
|
||||
|
||||
class NODE_MT_category_utilities_matrix(Menu):
|
||||
bl_idname = "NODE_MT_category_utilities_matrix"
|
||||
bl_label = "Matrix"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
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, "FunctionNodeSeparateTransform")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeTransformDirection")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeTransformPoint")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeTransposeMatrix")
|
||||
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Matrix")
|
||||
|
||||
|
||||
class NODE_MT_category_GEO_UTILITIES_MATH(Menu):
|
||||
bl_idname = "NODE_MT_category_GEO_UTILITIES_MATH"
|
||||
bl_label = "Math"
|
||||
|
@ -779,6 +797,7 @@ classes = (
|
|||
NODE_MT_category_GEO_UTILITIES_FIELD,
|
||||
NODE_MT_category_GEO_UTILITIES_MATH,
|
||||
NODE_MT_category_GEO_UTILITIES_ROTATION,
|
||||
NODE_MT_category_utilities_matrix,
|
||||
NODE_MT_category_GEO_UTILITIES_DEPRECATED,
|
||||
NODE_MT_category_GEO_GROUP,
|
||||
)
|
||||
|
|
|
@ -2661,6 +2661,7 @@ class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):
|
|||
({"property": "use_sculpt_texture_paint"}, ("blender/blender/issues/96225", "#96225")),
|
||||
({"property": "use_experimental_compositors"}, ("blender/blender/issues/88150", "#88150")),
|
||||
({"property": "use_grease_pencil_version3"}, ("blender/blender/projects/6", "Grease Pencil 3.0")),
|
||||
({"property": "use_new_matrix_socket"}, ("blender/blender/issues/116067", "Matrix Socket")),
|
||||
({"property": "enable_overlay_next"}, ("blender/blender/issues/102179", "#102179")),
|
||||
({"property": "use_extension_repos"}, ("/blender/blender/issues/106254", "#106254")),
|
||||
),
|
||||
|
|
|
@ -35,7 +35,8 @@ inline void convert_to_static_type(const CPPType &cpp_type, const Func &func)
|
|||
int8_t,
|
||||
ColorGeometry4f,
|
||||
ColorGeometry4b,
|
||||
math::Quaternion>([&](auto type_tag) {
|
||||
math::Quaternion,
|
||||
float4x4>([&](auto type_tag) {
|
||||
using T = typename decltype(type_tag)::type;
|
||||
if constexpr (std::is_same_v<T, void>) {
|
||||
/* It's expected that the given cpp type is one of the supported ones. */
|
||||
|
@ -517,6 +518,26 @@ class ColorGeometry4bMixer {
|
|||
void finalize(const IndexMask &mask);
|
||||
};
|
||||
|
||||
class float4x4Mixer {
|
||||
private:
|
||||
MutableSpan<float4x4> buffer_;
|
||||
Array<float> total_weights_;
|
||||
Array<float3> location_buffer_;
|
||||
Array<float3> expmap_buffer_;
|
||||
Array<float3> scale_buffer_;
|
||||
|
||||
public:
|
||||
float4x4Mixer(MutableSpan<float4x4> buffer);
|
||||
/**
|
||||
* \param mask: Only initialize these indices. Other indices in the buffer will be invalid.
|
||||
*/
|
||||
float4x4Mixer(MutableSpan<float4x4> buffer, const IndexMask &mask);
|
||||
void set(int64_t index, const float4x4 &value, float weight = 1.0f);
|
||||
void mix_in(int64_t index, const float4x4 &value, float weight = 1.0f);
|
||||
void finalize();
|
||||
void finalize(const IndexMask &mask);
|
||||
};
|
||||
|
||||
template<typename T> struct DefaultMixerStruct {
|
||||
/* Use void by default. This can be checked for in `if constexpr` statements. */
|
||||
using type = void;
|
||||
|
@ -538,6 +559,9 @@ template<> struct DefaultMixerStruct<ColorGeometry4f> {
|
|||
template<> struct DefaultMixerStruct<ColorGeometry4b> {
|
||||
using type = ColorGeometry4bMixer;
|
||||
};
|
||||
template<> struct DefaultMixerStruct<float4x4> {
|
||||
using type = float4x4Mixer;
|
||||
};
|
||||
template<> struct DefaultMixerStruct<int> {
|
||||
static double int_to_double(const int &value)
|
||||
{
|
||||
|
|
|
@ -1366,6 +1366,13 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
|
|||
#define FN_NODE_ROTATE_VECTOR 1229
|
||||
#define FN_NODE_ROTATE_ROTATION 1230
|
||||
#define FN_NODE_INVERT_ROTATION 1231
|
||||
#define FN_NODE_TRANSFORM_POINT 1232
|
||||
#define FN_NODE_TRANSFORM_DIRECTION 1233
|
||||
#define FN_NODE_MATRIX_MULTIPLY 1234
|
||||
#define FN_NODE_COMBINE_TRANSFORM 1235
|
||||
#define FN_NODE_SEPARATE_TRANSFORM 1236
|
||||
#define FN_NODE_INVERT_MATRIX 1237
|
||||
#define FN_NODE_TRANSPOSE_MATRIX 1238
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -130,6 +130,7 @@ static const bNodeSocketStaticTypeInfo node_socket_subtypes[] = {
|
|||
{"NodeSocketIntFactor", "NodeTreeInterfaceSocketIntFactor", SOCK_INT, PROP_FACTOR},
|
||||
{"NodeSocketBool", "NodeTreeInterfaceSocketBool", SOCK_BOOLEAN, PROP_NONE},
|
||||
{"NodeSocketRotation", "NodeTreeInterfaceSocketRotation", SOCK_ROTATION, PROP_NONE},
|
||||
{"NodeSocketMatrix", "NodeTreeInterfaceSocketMatrix", SOCK_MATRIX, PROP_NONE},
|
||||
{"NodeSocketVector", "NodeTreeInterfaceSocketVector", SOCK_VECTOR, PROP_NONE},
|
||||
{"NodeSocketVectorTranslation",
|
||||
"NodeTreeInterfaceSocketVectorTranslation",
|
||||
|
@ -206,6 +207,7 @@ template<typename Fn> bool socket_data_to_static_type(const eNodeSocketDatatype
|
|||
|
||||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_MATRIX:
|
||||
case SOCK_GEOMETRY:
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ const blender::CPPType *custom_data_type_to_cpp_type(const eCustomDataType type)
|
|||
return &CPPType::get<ColorGeometry4b>();
|
||||
case CD_PROP_QUATERNION:
|
||||
return &CPPType::get<math::Quaternion>();
|
||||
case CD_PROP_FLOAT4X4:
|
||||
return &CPPType::get<float4x4>();
|
||||
case CD_PROP_STRING:
|
||||
return &CPPType::get<MStringProperty>();
|
||||
default:
|
||||
|
@ -89,6 +91,9 @@ eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
|
|||
if (type.is<math::Quaternion>()) {
|
||||
return CD_PROP_QUATERNION;
|
||||
}
|
||||
if (type.is<float4x4>()) {
|
||||
return CD_PROP_FLOAT4X4;
|
||||
}
|
||||
if (type.is<MStringProperty>()) {
|
||||
return CD_PROP_STRING;
|
||||
}
|
||||
|
@ -167,6 +172,8 @@ static int attribute_data_type_complexity(const eCustomDataType data_type)
|
|||
return 8;
|
||||
case CD_PROP_COLOR:
|
||||
return 9;
|
||||
case CD_PROP_FLOAT4X4:
|
||||
return 10;
|
||||
#if 0 /* These attribute types are not supported yet. */
|
||||
case CD_PROP_STRING:
|
||||
return 10;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_array_utils.hh"
|
||||
#include "BLI_math_matrix.hh"
|
||||
#include "BLI_math_quaternion.hh"
|
||||
|
||||
#include "BKE_attribute_math.hh"
|
||||
|
@ -36,6 +37,40 @@ math::Quaternion mix4(const float4 &weights,
|
|||
return math::Quaternion::expmap(expmap_mixed);
|
||||
}
|
||||
|
||||
template<> float4x4 mix2(const float factor, const float4x4 &a, const float4x4 &b)
|
||||
{
|
||||
return math::interpolate(a, b, factor);
|
||||
}
|
||||
|
||||
template<>
|
||||
float4x4 mix3(const float3 &weights, const float4x4 &v0, const float4x4 &v1, const float4x4 &v2)
|
||||
{
|
||||
const float3 location = mix3(weights, v0.location(), v1.location(), v2.location());
|
||||
const math::Quaternion rotation = mix3(
|
||||
weights, math::to_quaternion(v0), math::to_quaternion(v1), math::to_quaternion(v2));
|
||||
const float3 scale = mix3(weights, math::to_scale(v0), math::to_scale(v1), math::to_scale(v2));
|
||||
return math::from_loc_rot_scale<float4x4>(location, rotation, scale);
|
||||
}
|
||||
|
||||
template<>
|
||||
float4x4 mix4(const float4 &weights,
|
||||
const float4x4 &v0,
|
||||
const float4x4 &v1,
|
||||
const float4x4 &v2,
|
||||
const float4x4 &v3)
|
||||
{
|
||||
const float3 location = mix4(
|
||||
weights, v0.location(), v1.location(), v2.location(), v3.location());
|
||||
const math::Quaternion rotation = mix4(weights,
|
||||
math::to_quaternion(v0),
|
||||
math::to_quaternion(v1),
|
||||
math::to_quaternion(v2),
|
||||
math::to_quaternion(v3));
|
||||
const float3 scale = mix4(
|
||||
weights, math::to_scale(v0), math::to_scale(v1), math::to_scale(v2), math::to_scale(v3));
|
||||
return math::from_loc_rot_scale<float4x4>(location, rotation, scale);
|
||||
}
|
||||
|
||||
ColorGeometry4fMixer::ColorGeometry4fMixer(MutableSpan<ColorGeometry4f> buffer,
|
||||
ColorGeometry4f default_color)
|
||||
: ColorGeometry4fMixer(buffer, buffer.index_range(), default_color)
|
||||
|
@ -160,6 +195,58 @@ void ColorGeometry4bMixer::finalize(const IndexMask &mask)
|
|||
});
|
||||
}
|
||||
|
||||
float4x4Mixer::float4x4Mixer(MutableSpan<float4x4> buffer)
|
||||
: float4x4Mixer(buffer, buffer.index_range())
|
||||
{
|
||||
}
|
||||
|
||||
float4x4Mixer::float4x4Mixer(MutableSpan<float4x4> buffer, const IndexMask & /*mask*/)
|
||||
: buffer_(buffer),
|
||||
total_weights_(buffer.size(), 0.0f),
|
||||
location_buffer_(buffer.size(), float3(0)),
|
||||
expmap_buffer_(buffer.size(), float3(0)),
|
||||
scale_buffer_(buffer.size(), float3(0))
|
||||
{
|
||||
}
|
||||
|
||||
void float4x4Mixer::float4x4Mixer::set(int64_t index, const float4x4 &value, const float weight)
|
||||
{
|
||||
location_buffer_[index] = value.location() * weight;
|
||||
expmap_buffer_[index] = math::to_quaternion(value).expmap() * weight;
|
||||
scale_buffer_[index] = math::to_scale(value) * weight;
|
||||
total_weights_[index] = weight;
|
||||
}
|
||||
|
||||
void float4x4Mixer::mix_in(int64_t index, const float4x4 &value, float weight)
|
||||
{
|
||||
location_buffer_[index] += value.location() * weight;
|
||||
expmap_buffer_[index] += math::to_quaternion(value).expmap() * weight;
|
||||
scale_buffer_[index] += math::to_scale(value) * weight;
|
||||
total_weights_[index] += weight;
|
||||
}
|
||||
|
||||
void float4x4Mixer::finalize()
|
||||
{
|
||||
this->finalize(buffer_.index_range());
|
||||
}
|
||||
|
||||
void float4x4Mixer::finalize(const IndexMask &mask)
|
||||
{
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float weight = total_weights_[i];
|
||||
if (weight > 0.0f) {
|
||||
const float weight_inv = math::rcp(weight);
|
||||
buffer_[i] = math::from_loc_rot_scale<float4x4>(
|
||||
location_buffer_[i] * weight_inv,
|
||||
math::Quaternion::expmap(expmap_buffer_[i] * weight_inv),
|
||||
scale_buffer_[i] * weight_inv);
|
||||
}
|
||||
else {
|
||||
buffer_[i] = float4x4::identity();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void gather(const GSpan src, const Span<int> map, GMutableSpan dst)
|
||||
{
|
||||
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
|
||||
|
|
|
@ -1042,6 +1042,10 @@ static std::shared_ptr<io::serialize::Value> serialize_primitive_value(
|
|||
const math::Quaternion value = *static_cast<const math::Quaternion *>(value_ptr);
|
||||
return serialize_float_array({&value.x, 4});
|
||||
}
|
||||
case CD_PROP_FLOAT4X4: {
|
||||
const float4x4 value = *static_cast<const float4x4 *>(value_ptr);
|
||||
return serialize_float_array({value.base_ptr(), value.col_len * value.row_len});
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1160,6 +1164,9 @@ template<typename T>
|
|||
case CD_PROP_QUATERNION: {
|
||||
return deserialize_float_array(io_value, {static_cast<float *>(r_value), 4});
|
||||
}
|
||||
case CD_PROP_FLOAT4X4: {
|
||||
return deserialize_float_array(io_value, {static_cast<float *>(r_value), 4 * 4});
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
|
|||
case SOCK_INT:
|
||||
case SOCK_BOOLEAN:
|
||||
case SOCK_ROTATION:
|
||||
case SOCK_MATRIX:
|
||||
case SOCK_RGBA: {
|
||||
auto &value_variant = *static_cast<SocketValueVariant *>(socket_value);
|
||||
if (value_variant.is_context_dependent_field()) {
|
||||
|
@ -131,6 +132,7 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
|
|||
case SOCK_INT:
|
||||
case SOCK_BOOLEAN:
|
||||
case SOCK_ROTATION:
|
||||
case SOCK_MATRIX:
|
||||
case SOCK_RGBA: {
|
||||
const CPPType &base_type = *socket_type_to_geo_nodes_base_cpp_type(socket_type);
|
||||
if (const auto *item = dynamic_cast<const PrimitiveBakeItem *>(&bake_item)) {
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "BLI_endian_switch.h"
|
||||
#include "BLI_index_range.hh"
|
||||
#include "BLI_math_color_blend.h"
|
||||
#include "BLI_math_matrix.hh"
|
||||
#include "BLI_math_quaternion_types.hh"
|
||||
#include "BLI_math_vector.hh"
|
||||
#include "BLI_mempool.h"
|
||||
|
@ -113,6 +114,7 @@ bool CustomData_MeshMasks_are_matching(const CustomData_MeshMasks *mask_ref,
|
|||
|
||||
struct LayerTypeInfo {
|
||||
int size; /* the memory size of one element of this layer's data */
|
||||
int alignment;
|
||||
|
||||
/** name of the struct used, for file writing */
|
||||
const char *structname;
|
||||
|
@ -1526,6 +1528,16 @@ static void layerDefault_propquaternion(void *data, const int count)
|
|||
MutableSpan(static_cast<math::Quaternion *>(data), count).fill(math::Quaternion::identity());
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Callbacks for (#math::Quaternion, #CD_PROP_FLOAT4X4)
|
||||
* \{ */
|
||||
|
||||
static void layerDefault_propfloat4x4(void *data, const int count)
|
||||
{
|
||||
using namespace blender;
|
||||
MutableSpan(static_cast<float4x4 *>(data), count).fill(float4x4::identity());
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -1534,11 +1546,30 @@ static void layerDefault_propquaternion(void *data, const int count)
|
|||
|
||||
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
||||
/* 0: CD_MVERT */ /* DEPRECATED */
|
||||
{sizeof(MVert), "MVert", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(MVert),
|
||||
alignof(MVert),
|
||||
"MVert",
|
||||
1,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 1: CD_MSTICKY */ /* DEPRECATED */
|
||||
{sizeof(float[2]), "", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(float[2]),
|
||||
alignof(float2),
|
||||
"",
|
||||
1,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 2: CD_MDEFORMVERT */
|
||||
{sizeof(MDeformVert),
|
||||
alignof(MDeformVert),
|
||||
"MDeformVert",
|
||||
1,
|
||||
nullptr,
|
||||
|
@ -1549,11 +1580,30 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
nullptr,
|
||||
layerConstruct_mdeformvert},
|
||||
/* 3: CD_MEDGE */ /* DEPRECATED */
|
||||
{sizeof(MEdge), "MEdge", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(MEdge),
|
||||
alignof(MEdge),
|
||||
"MEdge",
|
||||
1,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 4: CD_MFACE */
|
||||
{sizeof(MFace), "MFace", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(MFace),
|
||||
alignof(MFace),
|
||||
"MFace",
|
||||
1,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 5: CD_MTFACE */
|
||||
{sizeof(MTFace),
|
||||
alignof(MTFace),
|
||||
"MTFace",
|
||||
1,
|
||||
N_("UVMap"),
|
||||
|
@ -1576,18 +1626,31 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
layerMaxNum_tface},
|
||||
/* 6: CD_MCOL */
|
||||
/* 4 MCol structs per face */
|
||||
{sizeof(MCol[4]), "MCol", 4,
|
||||
N_("Col"), nullptr, nullptr,
|
||||
layerInterp_mcol, layerSwap_mcol, layerDefault_mcol,
|
||||
nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr},
|
||||
{sizeof(MCol[4]),
|
||||
alignof(MCol[4]),
|
||||
"MCol",
|
||||
4,
|
||||
N_("Col"),
|
||||
nullptr,
|
||||
nullptr,
|
||||
layerInterp_mcol,
|
||||
layerSwap_mcol,
|
||||
layerDefault_mcol},
|
||||
/* 7: CD_ORIGINDEX */
|
||||
{sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, layerDefault_origindex},
|
||||
{sizeof(int),
|
||||
alignof(int),
|
||||
"",
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
layerDefault_origindex},
|
||||
/* 8: CD_NORMAL */
|
||||
/* 3 floats per normal vector */
|
||||
{sizeof(float[3]),
|
||||
alignof(blender::float3),
|
||||
"vec3f",
|
||||
1,
|
||||
nullptr,
|
||||
|
@ -1605,9 +1668,10 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
nullptr,
|
||||
layerCopyValue_normal},
|
||||
/* 9: CD_FACEMAP */ /* DEPRECATED */
|
||||
{sizeof(int), ""},
|
||||
{sizeof(int), alignof(int), ""},
|
||||
/* 10: CD_PROP_FLOAT */
|
||||
{sizeof(MFloatProperty),
|
||||
alignof(float),
|
||||
"MFloatProperty",
|
||||
1,
|
||||
N_("Float"),
|
||||
|
@ -1620,6 +1684,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
layerValidate_propFloat},
|
||||
/* 11: CD_PROP_INT32 */
|
||||
{sizeof(MIntProperty),
|
||||
alignof(int),
|
||||
"MIntProperty",
|
||||
1,
|
||||
N_("Int"),
|
||||
|
@ -1629,6 +1694,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
nullptr},
|
||||
/* 12: CD_PROP_STRING */
|
||||
{sizeof(MStringProperty),
|
||||
alignof(MStringProperty),
|
||||
"MStringProperty",
|
||||
1,
|
||||
N_("String"),
|
||||
|
@ -1638,6 +1704,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
nullptr},
|
||||
/* 13: CD_ORIGSPACE */
|
||||
{sizeof(OrigSpaceFace),
|
||||
alignof(OrigSpaceFace),
|
||||
"OrigSpaceFace",
|
||||
1,
|
||||
N_("UVMap"),
|
||||
|
@ -1647,15 +1714,25 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
layerSwap_origspace_face,
|
||||
layerDefault_origspace_face},
|
||||
/* 14: CD_ORCO */
|
||||
{sizeof(float[3]), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(float[3]),
|
||||
alignof(blender::float3),
|
||||
"",
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 15: CD_MTEXPOLY */ /* DEPRECATED */
|
||||
/* NOTE: when we expose the UV Map / TexFace split to the user,
|
||||
* change this back to face Texture. */
|
||||
{sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(int), alignof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
/* 16: CD_MLOOPUV */ /* DEPRECATED */
|
||||
{sizeof(MLoopUV), "MLoopUV", 1, N_("UVMap")},
|
||||
{sizeof(MLoopUV), alignof(MLoopUV), "MLoopUV", 1, N_("UVMap")},
|
||||
/* 17: CD_PROP_BYTE_COLOR */
|
||||
{sizeof(MLoopCol),
|
||||
alignof(MLoopCol),
|
||||
"MLoopCol",
|
||||
1,
|
||||
N_("Col"),
|
||||
|
@ -1677,9 +1754,19 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
nullptr,
|
||||
nullptr},
|
||||
/* 18: CD_TANGENT */
|
||||
{sizeof(float[4][4]), "", 0, N_("Tangent"), nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(float[4][4]),
|
||||
alignof(float[4][4]),
|
||||
"",
|
||||
0,
|
||||
N_("Tangent"),
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 19: CD_MDISPS */
|
||||
{sizeof(MDisps),
|
||||
alignof(MDisps),
|
||||
"MDisps",
|
||||
1,
|
||||
nullptr,
|
||||
|
@ -1700,11 +1787,30 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
layerWrite_mdisps,
|
||||
layerFilesize_mdisps},
|
||||
/* 20: CD_PREVIEW_MCOL */
|
||||
{},
|
||||
{sizeof(blender::float4x4),
|
||||
alignof(blender::float4x4),
|
||||
"mat4x4f",
|
||||
1,
|
||||
N_("4 by 4 Float Matrix"),
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
layerDefault_propfloat4x4},
|
||||
/* 21: CD_ID_MCOL */ /* DEPRECATED */
|
||||
{sizeof(MCol[4]), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(MCol[4]),
|
||||
alignof(MCol[4]),
|
||||
"",
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 22: CD_TEXTURE_MCOL */
|
||||
{sizeof(MCol[4]),
|
||||
alignof(MCol[4]),
|
||||
"MCol",
|
||||
4,
|
||||
N_("TexturedCol"),
|
||||
|
@ -1714,13 +1820,40 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
layerSwap_mcol,
|
||||
layerDefault_mcol},
|
||||
/* 23: CD_CLOTH_ORCO */
|
||||
{sizeof(float[3]), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(float[3]),
|
||||
alignof(float[3]),
|
||||
"",
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 24: CD_RECAST */
|
||||
{sizeof(MRecast), "MRecast", 1, N_("Recast"), nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(MRecast),
|
||||
alignof(MRecast),
|
||||
"MRecast",
|
||||
1,
|
||||
N_("Recast"),
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 25: CD_MPOLY */ /* DEPRECATED */
|
||||
{sizeof(MPoly), "MPoly", 1, N_("NGon Face"), nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(MPoly),
|
||||
alignof(MPoly),
|
||||
"MPoly",
|
||||
1,
|
||||
N_("NGon Face"),
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 26: CD_MLOOP */ /* DEPRECATED */
|
||||
{sizeof(MLoop),
|
||||
alignof(MLoop),
|
||||
"MLoop",
|
||||
1,
|
||||
N_("NGon Face-Vertex"),
|
||||
|
@ -1730,15 +1863,23 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
nullptr,
|
||||
nullptr},
|
||||
/* 27: CD_SHAPE_KEYINDEX */
|
||||
{sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(int), alignof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
/* 28: CD_SHAPEKEY */
|
||||
{sizeof(float[3]), "", 0, N_("ShapeKey"), nullptr, nullptr, layerInterp_shapekey},
|
||||
{sizeof(float[3]),
|
||||
alignof(float[3]),
|
||||
"",
|
||||
0,
|
||||
N_("ShapeKey"),
|
||||
nullptr,
|
||||
nullptr,
|
||||
layerInterp_shapekey},
|
||||
/* 29: CD_BWEIGHT */ /* DEPRECATED */
|
||||
{sizeof(MFloatProperty), "MFloatProperty", 1},
|
||||
{sizeof(MFloatProperty), alignof(MFloatProperty), "MFloatProperty", 1},
|
||||
/* 30: CD_CREASE */ /* DEPRECATED */
|
||||
{sizeof(float), ""},
|
||||
{sizeof(float), alignof(float), ""},
|
||||
/* 31: CD_ORIGSPACE_MLOOP */
|
||||
{sizeof(OrigSpaceLoop),
|
||||
alignof(OrigSpaceLoop),
|
||||
"OrigSpaceLoop",
|
||||
1,
|
||||
N_("OS Loop"),
|
||||
|
@ -1759,6 +1900,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
{},
|
||||
/* 33: CD_BM_ELEM_PYPTR */
|
||||
{sizeof(void *),
|
||||
alignof(void *),
|
||||
"",
|
||||
1,
|
||||
nullptr,
|
||||
|
@ -1768,9 +1910,10 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
nullptr,
|
||||
nullptr},
|
||||
/* 34: CD_PAINT_MASK */ /* DEPRECATED */
|
||||
{sizeof(float), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(float), alignof(float), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
/* 35: CD_GRID_PAINT_MASK */
|
||||
{sizeof(GridPaintMask),
|
||||
alignof(GridPaintMask),
|
||||
"GridPaintMask",
|
||||
1,
|
||||
nullptr,
|
||||
|
@ -1782,6 +1925,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
layerConstruct_grid_paint_mask},
|
||||
/* 36: CD_MVERT_SKIN */
|
||||
{sizeof(MVertSkin),
|
||||
alignof(MVertSkin),
|
||||
"MVertSkin",
|
||||
1,
|
||||
nullptr,
|
||||
|
@ -1792,6 +1936,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
layerDefault_mvert_skin},
|
||||
/* 37: CD_FREESTYLE_EDGE */
|
||||
{sizeof(FreestyleEdge),
|
||||
alignof(FreestyleEdge),
|
||||
"FreestyleEdge",
|
||||
1,
|
||||
nullptr,
|
||||
|
@ -1802,6 +1947,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
nullptr},
|
||||
/* 38: CD_FREESTYLE_FACE */
|
||||
{sizeof(FreestyleFace),
|
||||
alignof(FreestyleFace),
|
||||
"FreestyleFace",
|
||||
1,
|
||||
nullptr,
|
||||
|
@ -1811,23 +1957,87 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
nullptr,
|
||||
nullptr},
|
||||
/* 39: CD_MLOOPTANGENT */
|
||||
{sizeof(float[4]), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(float[4]),
|
||||
alignof(float[4]),
|
||||
"",
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 40: CD_TESSLOOPNORMAL */
|
||||
{sizeof(short[4][3]), "", 0, nullptr, nullptr, nullptr, nullptr, layerSwap_flnor, nullptr},
|
||||
{sizeof(short[4][3]),
|
||||
alignof(short[4][3]),
|
||||
"",
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
layerSwap_flnor,
|
||||
nullptr},
|
||||
/* 41: CD_CUSTOMLOOPNORMAL */
|
||||
{sizeof(short[2]), "vec2s", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(short[2]),
|
||||
alignof(short[2]),
|
||||
"vec2s",
|
||||
1,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 42: CD_SCULPT_FACE_SETS */ /* DEPRECATED */
|
||||
{sizeof(int), ""},
|
||||
{sizeof(int), alignof(int), ""},
|
||||
/* 43: CD_LOCATION */
|
||||
{sizeof(float[3]), "vec3f", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(float[3]),
|
||||
alignof(float[3]),
|
||||
"vec3f",
|
||||
1,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 44: CD_RADIUS */
|
||||
{sizeof(float), "MFloatProperty", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(float),
|
||||
alignof(float),
|
||||
"MFloatProperty",
|
||||
1,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 45: CD_PROP_INT8 */
|
||||
{sizeof(int8_t), "MInt8Property", 1, N_("Int8"), nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(int8_t),
|
||||
alignof(int8_t),
|
||||
"MInt8Property",
|
||||
1,
|
||||
N_("Int8"),
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 46: CD_PROP_INT32_2D */
|
||||
{sizeof(blender::int2), "vec2i", 1, N_("Int 2D"), nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(blender::int2),
|
||||
alignof(blender::int2),
|
||||
"vec2i",
|
||||
1,
|
||||
N_("Int 2D"),
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 47: CD_PROP_COLOR */
|
||||
{sizeof(MPropCol),
|
||||
alignof(MPropCol),
|
||||
"MPropCol",
|
||||
1,
|
||||
N_("Color"),
|
||||
|
@ -1850,6 +2060,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
nullptr},
|
||||
/* 48: CD_PROP_FLOAT3 */
|
||||
{sizeof(float[3]),
|
||||
alignof(blender::float3),
|
||||
"vec3f",
|
||||
1,
|
||||
N_("Float3"),
|
||||
|
@ -1866,6 +2077,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
layerAdd_propfloat3},
|
||||
/* 49: CD_PROP_FLOAT2 */
|
||||
{sizeof(float[2]),
|
||||
alignof(float2),
|
||||
"vec2f",
|
||||
1,
|
||||
N_("Float2"),
|
||||
|
@ -1884,6 +2096,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
layerCopyValue_propfloat2},
|
||||
/* 50: CD_PROP_BOOL */
|
||||
{sizeof(bool),
|
||||
alignof(bool),
|
||||
"bool",
|
||||
1,
|
||||
N_("Boolean"),
|
||||
|
@ -1898,9 +2111,19 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
nullptr,
|
||||
nullptr},
|
||||
/* 51: CD_HAIRLENGTH */ /* DEPRECATED */ /* UNUSED */
|
||||
{sizeof(float), "float", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
{sizeof(float),
|
||||
alignof(float),
|
||||
"float",
|
||||
1,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr},
|
||||
/* 52: CD_PROP_QUATERNION */
|
||||
{sizeof(float[4]),
|
||||
alignof(blender::float4),
|
||||
"vec4f",
|
||||
1,
|
||||
N_("Quaternion"),
|
||||
|
@ -2134,12 +2357,15 @@ static bool customdata_typemap_is_valid(const CustomData *data)
|
|||
static void *copy_layer_data(const eCustomDataType type, const void *data, const int totelem)
|
||||
{
|
||||
const LayerTypeInfo &type_info = *layerType_getInfo(type);
|
||||
const int64_t size_in_bytes = int64_t(totelem) * type_info.size;
|
||||
void *new_data = MEM_mallocN_aligned(size_in_bytes, type_info.alignment, __func__);
|
||||
if (type_info.copy) {
|
||||
void *new_data = MEM_malloc_arrayN(size_t(totelem), type_info.size, __func__);
|
||||
type_info.copy(data, new_data, totelem);
|
||||
return new_data;
|
||||
}
|
||||
return MEM_dupallocN(data);
|
||||
else {
|
||||
memcpy(new_data, data, size_in_bytes);
|
||||
}
|
||||
return new_data;
|
||||
}
|
||||
|
||||
static void free_layer_data(const eCustomDataType type, const void *data, const int totelem)
|
||||
|
@ -2389,7 +2615,7 @@ void CustomData_realloc(CustomData *data,
|
|||
const int64_t old_size_in_bytes = int64_t(old_size) * typeInfo->size;
|
||||
const int64_t new_size_in_bytes = int64_t(new_size) * typeInfo->size;
|
||||
|
||||
void *new_layer_data = MEM_mallocN(new_size_in_bytes, __func__);
|
||||
void *new_layer_data = MEM_mallocN_aligned(new_size_in_bytes, typeInfo->alignment, __func__);
|
||||
/* Copy data to new array. */
|
||||
if (old_size_in_bytes) {
|
||||
if (typeInfo->copy) {
|
||||
|
@ -2877,23 +3103,27 @@ static CustomDataLayer *customData_add_layer__internal(
|
|||
* leaks into the new layer. */
|
||||
memset(&new_layer, 0, sizeof(CustomDataLayer));
|
||||
|
||||
const int64_t size_in_bytes = int64_t(totelem) * type_info.size;
|
||||
const char *alloc_name = layerType_getName(type);
|
||||
|
||||
if (alloctype.has_value()) {
|
||||
switch (*alloctype) {
|
||||
case CD_SET_DEFAULT: {
|
||||
if (totelem > 0) {
|
||||
new_layer.data = MEM_mallocN_aligned(size_in_bytes, type_info.alignment, alloc_name);
|
||||
if (type_info.set_default_value) {
|
||||
new_layer.data = MEM_malloc_arrayN(totelem, type_info.size, layerType_getName(type));
|
||||
type_info.set_default_value(new_layer.data, totelem);
|
||||
}
|
||||
else {
|
||||
new_layer.data = MEM_calloc_arrayN(totelem, type_info.size, layerType_getName(type));
|
||||
/* Alternatively, #MEM_calloc_arrayN is faster, but has no aligned version. */
|
||||
memset(new_layer.data, 0, size_in_bytes);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CD_CONSTRUCT: {
|
||||
if (totelem > 0) {
|
||||
new_layer.data = MEM_malloc_arrayN(totelem, type_info.size, layerType_getName(type));
|
||||
new_layer.data = MEM_mallocN_aligned(size_in_bytes, type_info.alignment, alloc_name);
|
||||
if (type_info.construct) {
|
||||
type_info.construct(new_layer.data, totelem);
|
||||
}
|
||||
|
|
|
@ -132,6 +132,9 @@ static void sort_indices(MutableSpan<int> indices, const Span<T> values, const i
|
|||
const float4 value2_quat = float4(value2);
|
||||
return value1_quat[component_i] < value2_quat[component_i];
|
||||
}
|
||||
if constexpr (std::is_same_v<T, float4x4>) {
|
||||
return value1.base_ptr()[component_i] < value2.base_ptr()[component_i];
|
||||
}
|
||||
if constexpr (std::is_same_v<T, int2>) {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (value1[i] != value2[i]) {
|
||||
|
@ -248,6 +251,10 @@ static bool values_different(const T value1,
|
|||
const float4 value2_f = float4(value2);
|
||||
return compare_threshold_relative(value1_f[component_i], value2_f[component_i], threshold);
|
||||
}
|
||||
if constexpr (std::is_same_v<T, float4x4>) {
|
||||
return compare_threshold_relative(
|
||||
value1.base_ptr()[component_i], value2.base_ptr()[component_i], threshold);
|
||||
}
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
|
||||
|
@ -575,6 +582,9 @@ static std::optional<MeshMismatch> sort_domain_using_attributes(
|
|||
else if constexpr (is_same_any_v<T, math::Quaternion, ColorGeometry4f>) {
|
||||
num_loops = 4;
|
||||
}
|
||||
else if constexpr (is_same_any_v<T, float4x4>) {
|
||||
num_loops = 16;
|
||||
}
|
||||
for (const int component_i : IndexRange(num_loops)) {
|
||||
sort_per_set_based_on_attributes(
|
||||
maps.set_sizes, maps.from_sorted1, maps.from_sorted2, values1, values2, component_i);
|
||||
|
|
|
@ -353,6 +353,7 @@ static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket
|
|||
case SOCK_RGBA:
|
||||
case SOCK_BOOLEAN:
|
||||
case SOCK_ROTATION:
|
||||
case SOCK_MATRIX:
|
||||
case SOCK_INT:
|
||||
case SOCK_STRING:
|
||||
case SOCK_CUSTOM:
|
||||
|
@ -703,10 +704,12 @@ static void write_node_socket_default_value(BlendWriter *writer, const bNodeSock
|
|||
case SOCK_ROTATION:
|
||||
BLO_write_struct(writer, bNodeSocketValueRotation, sock->default_value);
|
||||
break;
|
||||
case SOCK_MENU: {
|
||||
case SOCK_MENU:
|
||||
BLO_write_struct(writer, bNodeSocketValueMenu, sock->default_value);
|
||||
break;
|
||||
}
|
||||
case SOCK_MATRIX:
|
||||
/* Matrix sockets currently have no default value. */
|
||||
break;
|
||||
case SOCK_CUSTOM:
|
||||
/* Custom node sockets where default_value is defined uses custom properties for storage. */
|
||||
break;
|
||||
|
@ -939,6 +942,7 @@ static bool is_node_socket_supported(const bNodeSocket *sock)
|
|||
case SOCK_MATERIAL:
|
||||
case SOCK_ROTATION:
|
||||
case SOCK_MENU:
|
||||
case SOCK_MATRIX:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1863,6 +1867,7 @@ static void socket_id_user_increment(bNodeSocket *sock)
|
|||
case SOCK_RGBA:
|
||||
case SOCK_BOOLEAN:
|
||||
case SOCK_ROTATION:
|
||||
case SOCK_MATRIX:
|
||||
case SOCK_INT:
|
||||
case SOCK_STRING:
|
||||
case SOCK_MENU:
|
||||
|
@ -1910,6 +1915,7 @@ static bool socket_id_user_decrement(bNodeSocket *sock)
|
|||
case SOCK_RGBA:
|
||||
case SOCK_BOOLEAN:
|
||||
case SOCK_ROTATION:
|
||||
case SOCK_MATRIX:
|
||||
case SOCK_INT:
|
||||
case SOCK_STRING:
|
||||
case SOCK_MENU:
|
||||
|
@ -1965,6 +1971,7 @@ void nodeModifySocketType(bNodeTree *ntree,
|
|||
case SOCK_SHADER:
|
||||
case SOCK_BOOLEAN:
|
||||
case SOCK_ROTATION:
|
||||
case SOCK_MATRIX:
|
||||
case SOCK_CUSTOM:
|
||||
case SOCK_OBJECT:
|
||||
case SOCK_IMAGE:
|
||||
|
@ -2071,6 +2078,8 @@ const char *nodeStaticSocketType(const int type, const int subtype)
|
|||
return "NodeSocketBool";
|
||||
case SOCK_ROTATION:
|
||||
return "NodeSocketRotation";
|
||||
case SOCK_MATRIX:
|
||||
return "NodeSocketMatrix";
|
||||
case SOCK_VECTOR:
|
||||
switch (PropertySubType(subtype)) {
|
||||
case PROP_TRANSLATION:
|
||||
|
@ -2154,6 +2163,8 @@ const char *nodeStaticSocketInterfaceTypeNew(const int type, const int subtype)
|
|||
return "NodeTreeInterfaceSocketBool";
|
||||
case SOCK_ROTATION:
|
||||
return "NodeTreeInterfaceSocketRotation";
|
||||
case SOCK_MATRIX:
|
||||
return "NodeTreeInterfaceSocketMatrix";
|
||||
case SOCK_VECTOR:
|
||||
switch (PropertySubType(subtype)) {
|
||||
case PROP_TRANSLATION:
|
||||
|
@ -2209,6 +2220,8 @@ const char *nodeStaticSocketLabel(const int type, const int /*subtype*/)
|
|||
return "Boolean";
|
||||
case SOCK_ROTATION:
|
||||
return "Rotation";
|
||||
case SOCK_MATRIX:
|
||||
return "Matrix";
|
||||
case SOCK_VECTOR:
|
||||
return "Vector";
|
||||
case SOCK_RGBA:
|
||||
|
@ -2756,6 +2769,9 @@ static void *socket_value_storage(bNodeSocket &socket)
|
|||
return &socket.default_value_typed<bNodeSocketValueRotation>()->value_euler;
|
||||
case SOCK_MENU:
|
||||
return &socket.default_value_typed<bNodeSocketValueMenu>()->value;
|
||||
case SOCK_MATRIX:
|
||||
/* Matrix sockets currently have no default value. */
|
||||
return nullptr;
|
||||
case SOCK_STRING:
|
||||
/* We don't want do this now! */
|
||||
return nullptr;
|
||||
|
@ -4344,6 +4360,8 @@ std::optional<eCustomDataType> socket_type_to_custom_data_type(eNodeSocketDataty
|
|||
return CD_PROP_BOOL;
|
||||
case SOCK_ROTATION:
|
||||
return CD_PROP_QUATERNION;
|
||||
case SOCK_MATRIX:
|
||||
return CD_PROP_FLOAT4X4;
|
||||
case SOCK_INT:
|
||||
return CD_PROP_INT32;
|
||||
case SOCK_STRING:
|
||||
|
@ -4372,6 +4390,8 @@ std::optional<eNodeSocketDatatype> custom_data_type_to_socket_type(eCustomDataTy
|
|||
return SOCK_RGBA;
|
||||
case CD_PROP_QUATERNION:
|
||||
return SOCK_ROTATION;
|
||||
case CD_PROP_FLOAT4X4:
|
||||
return SOCK_MATRIX;
|
||||
default:
|
||||
return std::nullopt;
|
||||
}
|
||||
|
@ -4434,6 +4454,9 @@ std::optional<eNodeSocketDatatype> geo_nodes_base_cpp_type_to_socket_type(const
|
|||
if (type.is<math::Quaternion>()) {
|
||||
return SOCK_ROTATION;
|
||||
}
|
||||
if (type.is<float4x4>()) {
|
||||
return SOCK_MATRIX;
|
||||
}
|
||||
if (type.is<std::string>()) {
|
||||
return SOCK_STRING;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,9 @@ template<typename T> static std::optional<eNodeSocketDatatype> static_type_to_so
|
|||
if constexpr (is_single_or_field_or_grid_v<T, math::Quaternion>) {
|
||||
return SOCK_ROTATION;
|
||||
}
|
||||
if constexpr (is_same_any_v<T, float4x4, fn::Field<float4x4>>) {
|
||||
return SOCK_MATRIX;
|
||||
}
|
||||
if constexpr (is_same_any_v<T, std::string>) {
|
||||
return SOCK_STRING;
|
||||
}
|
||||
|
@ -195,6 +198,10 @@ void SocketValueVariant::store_single(const eNodeSocketDatatype socket_type, con
|
|||
value_.emplace<math::Quaternion>(*static_cast<const math::Quaternion *>(value));
|
||||
break;
|
||||
}
|
||||
case SOCK_MATRIX: {
|
||||
value_.emplace<float4x4>(*static_cast<const float4x4 *>(value));
|
||||
break;
|
||||
}
|
||||
case SOCK_RGBA: {
|
||||
value_.emplace<ColorGeometry4f>(*static_cast<const ColorGeometry4f *>(value));
|
||||
break;
|
||||
|
@ -281,6 +288,8 @@ void *SocketValueVariant::allocate_single(const eNodeSocketDatatype socket_type)
|
|||
return value_.allocate<bool>();
|
||||
case SOCK_ROTATION:
|
||||
return value_.allocate<math::Quaternion>();
|
||||
case SOCK_MATRIX:
|
||||
return value_.allocate<float4x4>();
|
||||
case SOCK_RGBA:
|
||||
return value_.allocate<ColorGeometry4f>();
|
||||
case SOCK_STRING:
|
||||
|
@ -344,6 +353,9 @@ INSTANTIATE_SINGLE_AND_FIELD_AND_GRID(blender::math::Quaternion)
|
|||
INSTANTIATE(std::string)
|
||||
INSTANTIATE(fn::GField)
|
||||
|
||||
INSTANTIATE(float4x4)
|
||||
INSTANTIATE(fn::Field<float4x4>)
|
||||
|
||||
#ifdef WITH_OPENVDB
|
||||
INSTANTIATE(GVolumeGrid)
|
||||
#endif
|
||||
|
|
|
@ -349,11 +349,21 @@ static ColorGeometry4f byte_color_to_color(const ColorGeometry4b &a)
|
|||
return a.decode();
|
||||
}
|
||||
|
||||
static math::Quaternion float4x4_to_quaternion(const float4x4 &a)
|
||||
{
|
||||
return math::to_quaternion(a);
|
||||
}
|
||||
|
||||
static float3 quaternion_to_float3(const math::Quaternion &a)
|
||||
{
|
||||
return float3(math::to_euler(a).xyz());
|
||||
}
|
||||
|
||||
static float4x4 quaternion_to_float4x4(const math::Quaternion &a)
|
||||
{
|
||||
return math::from_rotation<float4x4>(a);
|
||||
}
|
||||
|
||||
static DataTypeConversions create_implicit_conversions()
|
||||
{
|
||||
DataTypeConversions conversions;
|
||||
|
@ -441,7 +451,10 @@ static DataTypeConversions create_implicit_conversions()
|
|||
add_implicit_conversion<ColorGeometry4b, float3, byte_color_to_float3>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4b, ColorGeometry4f, byte_color_to_color>(conversions);
|
||||
|
||||
add_implicit_conversion<float4x4, math::Quaternion, float4x4_to_quaternion>(conversions);
|
||||
|
||||
add_implicit_conversion<math::Quaternion, float3, quaternion_to_float3>(conversions);
|
||||
add_implicit_conversion<math::Quaternion, float4x4, quaternion_to_float4x4>(conversions);
|
||||
|
||||
return conversions;
|
||||
}
|
||||
|
|
|
@ -23,11 +23,13 @@ GPUVertFormat init_format_for_attribute(const eCustomDataType data_type,
|
|||
bke::attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
using Converter = AttributeConverter<T>;
|
||||
GPU_vertformat_attr_add(&format,
|
||||
vbo_name.c_str(),
|
||||
Converter::gpu_component_type,
|
||||
Converter::gpu_component_len,
|
||||
Converter::gpu_fetch_mode);
|
||||
if constexpr (!std::is_void_v<typename Converter::VBOType>) {
|
||||
GPU_vertformat_attr_add(&format,
|
||||
vbo_name.c_str(),
|
||||
Converter::gpu_component_type,
|
||||
Converter::gpu_component_len,
|
||||
Converter::gpu_fetch_mode);
|
||||
}
|
||||
});
|
||||
return format;
|
||||
}
|
||||
|
@ -38,18 +40,20 @@ void vertbuf_data_extract_direct(const GSpan attribute, GPUVertBuf &vbo)
|
|||
using T = decltype(dummy);
|
||||
using Converter = AttributeConverter<T>;
|
||||
using VBOType = typename Converter::VBOType;
|
||||
const Span<T> src = attribute.typed<T>();
|
||||
MutableSpan<VBOType> data(static_cast<VBOType *>(GPU_vertbuf_get_data(&vbo)),
|
||||
attribute.size());
|
||||
if constexpr (std::is_same_v<T, VBOType>) {
|
||||
array_utils::copy(src, data);
|
||||
}
|
||||
else {
|
||||
threading::parallel_for(src.index_range(), 8192, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
data[i] = Converter::convert(src[i]);
|
||||
}
|
||||
});
|
||||
if constexpr (!std::is_void_v<VBOType>) {
|
||||
const Span<T> src = attribute.typed<T>();
|
||||
MutableSpan<VBOType> data(static_cast<VBOType *>(GPU_vertbuf_get_data(&vbo)),
|
||||
attribute.size());
|
||||
if constexpr (std::is_same_v<T, VBOType>) {
|
||||
array_utils::copy(src, data);
|
||||
}
|
||||
else {
|
||||
threading::parallel_for(src.index_range(), 8192, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
data[i] = Converter::convert(src[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -582,9 +582,11 @@ struct PBVHBatches {
|
|||
using T = decltype(dummy);
|
||||
using Converter = AttributeConverter<T>;
|
||||
using VBOType = typename Converter::VBOType;
|
||||
std::fill_n(static_cast<VBOType *>(GPU_vertbuf_get_data(vbo.vert_buf)),
|
||||
GPU_vertbuf_get_vertex_len(vbo.vert_buf),
|
||||
VBOType());
|
||||
if constexpr (!std::is_void_v<VBOType>) {
|
||||
std::fill_n(static_cast<VBOType *>(GPU_vertbuf_get_data(vbo.vert_buf)),
|
||||
GPU_vertbuf_get_vertex_len(vbo.vert_buf),
|
||||
VBOType());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -754,18 +756,20 @@ struct PBVHBatches {
|
|||
const GVArraySpan attribute = *attributes.lookup_or_default(name, domain, data_type);
|
||||
bke::attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
switch (domain) {
|
||||
case bke::AttrDomain::Point:
|
||||
extract_data_vert_faces<T>(args, attribute.typed<T>(), vert_buf);
|
||||
break;
|
||||
case bke::AttrDomain::Face:
|
||||
extract_data_face_faces<T>(args, attribute.typed<T>(), vert_buf);
|
||||
break;
|
||||
case bke::AttrDomain::Corner:
|
||||
extract_data_corner_faces<T>(args, attribute.typed<T>(), vert_buf);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
if constexpr (!std::is_void_v<typename AttributeConverter<T>::VBOType>) {
|
||||
switch (domain) {
|
||||
case bke::AttrDomain::Point:
|
||||
extract_data_vert_faces<T>(args, attribute.typed<T>(), vert_buf);
|
||||
break;
|
||||
case bke::AttrDomain::Face:
|
||||
extract_data_face_faces<T>(args, attribute.typed<T>(), vert_buf);
|
||||
break;
|
||||
case bke::AttrDomain::Corner:
|
||||
extract_data_corner_faces<T>(args, attribute.typed<T>(), vert_buf);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -920,18 +924,20 @@ struct PBVHBatches {
|
|||
const int cd_offset = CustomData_get_offset_named(&custom_data, data_type, request.name);
|
||||
bke::attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
switch (domain) {
|
||||
case bke::AttrDomain::Point:
|
||||
extract_data_vert_bmesh<T>(args, cd_offset, *vbo.vert_buf);
|
||||
break;
|
||||
case bke::AttrDomain::Face:
|
||||
extract_data_face_bmesh<T>(args, cd_offset, *vbo.vert_buf);
|
||||
break;
|
||||
case bke::AttrDomain::Corner:
|
||||
extract_data_corner_bmesh<T>(args, cd_offset, *vbo.vert_buf);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
if constexpr (!std::is_void_v<typename AttributeConverter<T>::VBOType>) {
|
||||
switch (domain) {
|
||||
case bke::AttrDomain::Point:
|
||||
extract_data_vert_bmesh<T>(args, cd_offset, *vbo.vert_buf);
|
||||
break;
|
||||
case bke::AttrDomain::Face:
|
||||
extract_data_face_bmesh<T>(args, cd_offset, *vbo.vert_buf);
|
||||
break;
|
||||
case bke::AttrDomain::Corner:
|
||||
extract_data_corner_bmesh<T>(args, cd_offset, *vbo.vert_buf);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -199,21 +199,23 @@ static void extract_attribute(const MeshRenderData &mr,
|
|||
|
||||
bke::attribute_math::convert_to_static_type(request.cd_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
switch (request.domain) {
|
||||
case bke::AttrDomain::Point:
|
||||
extract_data_bmesh_vert<T>(*mr.bm, cd_offset, vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Edge:
|
||||
extract_data_bmesh_edge<T>(*mr.bm, cd_offset, vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Face:
|
||||
extract_data_bmesh_face<T>(*mr.bm, cd_offset, vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Corner:
|
||||
extract_data_bmesh_loop<T>(*mr.bm, cd_offset, vbo);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
if constexpr (!std::is_void_v<typename AttributeConverter<T>::VBOType>) {
|
||||
switch (request.domain) {
|
||||
case bke::AttrDomain::Point:
|
||||
extract_data_bmesh_vert<T>(*mr.bm, cd_offset, vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Edge:
|
||||
extract_data_bmesh_edge<T>(*mr.bm, cd_offset, vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Face:
|
||||
extract_data_bmesh_face<T>(*mr.bm, cd_offset, vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Corner:
|
||||
extract_data_bmesh_loop<T>(*mr.bm, cd_offset, vbo);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -225,21 +227,23 @@ static void extract_attribute(const MeshRenderData &mr,
|
|||
|
||||
bke::attribute_math::convert_to_static_type(request.cd_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
switch (request.domain) {
|
||||
case bke::AttrDomain::Point:
|
||||
extract_data_mesh_mapped_corner(attribute.typed<T>(), mr.corner_verts, vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Edge:
|
||||
extract_data_mesh_mapped_corner(attribute.typed<T>(), mr.corner_edges, vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Face:
|
||||
extract_data_mesh_face(mr.faces, attribute.typed<T>(), vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Corner:
|
||||
vertbuf_data_extract_direct(attribute.typed<T>(), vbo);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
if constexpr (!std::is_void_v<typename AttributeConverter<T>::VBOType>) {
|
||||
switch (request.domain) {
|
||||
case bke::AttrDomain::Point:
|
||||
extract_data_mesh_mapped_corner(attribute.typed<T>(), mr.corner_verts, vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Edge:
|
||||
extract_data_mesh_mapped_corner(attribute.typed<T>(), mr.corner_edges, vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Face:
|
||||
extract_data_mesh_face(mr.faces, attribute.typed<T>(), vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Corner:
|
||||
vertbuf_data_extract_direct(attribute.typed<T>(), vbo);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -282,12 +286,14 @@ static void extract_attr_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
|||
bke::attribute_math::convert_to_static_type(request.cd_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
using Converter = AttributeConverter<T>;
|
||||
draw_subdiv_interp_custom_data(subdiv_cache,
|
||||
src_data,
|
||||
dst_buffer,
|
||||
Converter::gpu_component_type,
|
||||
Converter::gpu_component_len,
|
||||
0);
|
||||
if constexpr (!std::is_void_v<typename Converter::VBOType>) {
|
||||
draw_subdiv_interp_custom_data(subdiv_cache,
|
||||
src_data,
|
||||
dst_buffer,
|
||||
Converter::gpu_component_type,
|
||||
Converter::gpu_component_len,
|
||||
0);
|
||||
}
|
||||
});
|
||||
|
||||
GPU_vertbuf_discard(src_data);
|
||||
|
|
|
@ -1201,6 +1201,7 @@ static const float std_node_socket_colors[][4] = {
|
|||
{0.92, 0.46, 0.51, 1.0}, /* SOCK_MATERIAL */
|
||||
{0.65, 0.39, 0.78, 1.0}, /* SOCK_ROTATION */
|
||||
{0.40, 0.40, 0.40, 1.0}, /* SOCK_MENU */
|
||||
{0.72, 0.20, 0.52, 1.0}, /* SOCK_MATRIX */
|
||||
};
|
||||
|
||||
/* Callback for colors that does not depend on the socket pointer argument to get the type. */
|
||||
|
@ -1236,6 +1237,7 @@ static const SocketColorFn std_node_socket_color_funcs[] = {
|
|||
std_node_socket_color_fn<SOCK_MATERIAL>,
|
||||
std_node_socket_color_fn<SOCK_ROTATION>,
|
||||
std_node_socket_color_fn<SOCK_MENU>,
|
||||
std_node_socket_color_fn<SOCK_MATRIX>,
|
||||
};
|
||||
|
||||
/* draw function for file output node sockets,
|
||||
|
@ -1350,6 +1352,10 @@ static void std_node_socket_draw(
|
|||
uiItemR(column, ptr, "default_value", DEFAULT_FLAGS, text, ICON_NONE);
|
||||
break;
|
||||
}
|
||||
case SOCK_MATRIX: {
|
||||
uiItemL(layout, text, ICON_NONE);
|
||||
break;
|
||||
}
|
||||
case SOCK_RGBA: {
|
||||
if (text[0] == '\0') {
|
||||
uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
|
||||
|
@ -1528,6 +1534,7 @@ static void std_node_socket_interface_draw(ID *id,
|
|||
}
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_MATRIX:
|
||||
break;
|
||||
|
||||
case SOCK_CUSTOM:
|
||||
|
|
|
@ -1303,6 +1303,14 @@ static void create_inspection_string_for_generic_value(const bNodeSocket &socket
|
|||
ss << fmt::format(TIP_("{} (Boolean)"),
|
||||
((*static_cast<bool *>(socket_value)) ? TIP_("True") : TIP_("False")));
|
||||
}
|
||||
else if (socket_type.is<float4x4>()) {
|
||||
const float4x4 &value = *static_cast<const float4x4 *>(socket_value);
|
||||
ss << value[0] << ",\n";
|
||||
ss << value[1] << ",\n";
|
||||
ss << value[2] << ",\n";
|
||||
ss << value[3] << ",\n";
|
||||
ss << TIP_("(Matrix)");
|
||||
}
|
||||
}
|
||||
|
||||
static void create_inspection_string_for_field_info(const bNodeSocket &socket,
|
||||
|
|
|
@ -157,6 +157,7 @@ static eCustomDataType data_type_in_attribute_input_node(const eCustomDataType t
|
|||
case CD_PROP_COLOR:
|
||||
case CD_PROP_BOOL:
|
||||
case CD_PROP_QUATERNION:
|
||||
case CD_PROP_FLOAT4X4:
|
||||
return type;
|
||||
case CD_PROP_BYTE_COLOR:
|
||||
return CD_PROP_COLOR;
|
||||
|
|
|
@ -2230,6 +2230,7 @@ static int get_main_socket_priority(const bNodeSocket *socket)
|
|||
case SOCK_OBJECT:
|
||||
case SOCK_IMAGE:
|
||||
case SOCK_ROTATION:
|
||||
case SOCK_MATRIX:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_COLLECTION:
|
||||
case SOCK_TEXTURE:
|
||||
|
|
|
@ -391,6 +391,9 @@ static Vector<NodeLinkItem> ui_node_link_items(NodeLinkArg *arg,
|
|||
else if (dynamic_cast<const decl::Rotation *>(&socket_decl)) {
|
||||
item.socket_type = SOCK_ROTATION;
|
||||
}
|
||||
else if (dynamic_cast<const decl::Matrix *>(&socket_decl)) {
|
||||
item.socket_type = SOCK_MATRIX;
|
||||
}
|
||||
else if (dynamic_cast<const decl::String *>(&socket_decl)) {
|
||||
item.socket_type = SOCK_STRING;
|
||||
}
|
||||
|
|
|
@ -339,6 +339,7 @@ static float get_default_column_width(const ColumnValues &values)
|
|||
static const float float_width = 3;
|
||||
switch (values.type()) {
|
||||
case SPREADSHEET_VALUE_TYPE_BOOL:
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT4X4:
|
||||
return 2.0f;
|
||||
case SPREADSHEET_VALUE_TYPE_INT8:
|
||||
case SPREADSHEET_VALUE_TYPE_INT32:
|
||||
|
|
|
@ -60,6 +60,9 @@ eSpreadsheetColumnValueType cpp_type_to_column_type(const CPPType &type)
|
|||
if (type.is<math::Quaternion>()) {
|
||||
return SPREADSHEET_VALUE_TYPE_QUATERNION;
|
||||
}
|
||||
if (type.is<float4x4>()) {
|
||||
return SPREADSHEET_VALUE_TYPE_FLOAT4X4;
|
||||
}
|
||||
|
||||
return SPREADSHEET_VALUE_TYPE_UNKNOWN;
|
||||
}
|
||||
|
|
|
@ -209,6 +209,9 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer {
|
|||
const float4 value = float4(data.get<math::Quaternion>(real_index));
|
||||
this->draw_float_vector(params, Span(&value.x, 4));
|
||||
}
|
||||
else if (data.type().is<float4x4>()) {
|
||||
this->draw_float4x4(params, data.get<float4x4>(real_index));
|
||||
}
|
||||
else if (data.type().is<bke::InstanceReference>()) {
|
||||
const bke::InstanceReference value = data.get<bke::InstanceReference>(real_index);
|
||||
switch (value.type()) {
|
||||
|
@ -398,6 +401,40 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer {
|
|||
}
|
||||
}
|
||||
|
||||
void draw_float4x4(const CellDrawParams ¶ms, const float4x4 &value) const
|
||||
{
|
||||
uiBut *but = uiDefIconTextBut(params.block,
|
||||
UI_BTYPE_LABEL,
|
||||
0,
|
||||
ICON_NONE,
|
||||
"...",
|
||||
params.xmin,
|
||||
params.ymin,
|
||||
params.width,
|
||||
params.height,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr);
|
||||
/* Center alignment. */
|
||||
UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
|
||||
UI_but_func_tooltip_set(
|
||||
but,
|
||||
[](bContext * /*C*/, void *argN, const char * /*tip*/) {
|
||||
const float4x4 &value = *static_cast<const float4x4 *>(argN);
|
||||
std::stringstream ss;
|
||||
ss << value[0] << ",\n";
|
||||
ss << value[1] << ",\n";
|
||||
ss << value[2] << ",\n";
|
||||
ss << value[3];
|
||||
return ss.str();
|
||||
},
|
||||
MEM_new<float4x4>(__func__, value),
|
||||
MEM_freeN);
|
||||
}
|
||||
|
||||
int column_width(int column_index) const final
|
||||
{
|
||||
return spreadsheet_layout_.columns[column_index].width;
|
||||
|
|
|
@ -109,6 +109,7 @@ static std::string value_string(const SpreadsheetRowFilter &row_filter,
|
|||
case SPREADSHEET_VALUE_TYPE_STRING:
|
||||
return row_filter.value_string;
|
||||
case SPREADSHEET_VALUE_TYPE_QUATERNION:
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT4X4:
|
||||
case SPREADSHEET_VALUE_TYPE_UNKNOWN:
|
||||
return "";
|
||||
}
|
||||
|
@ -253,6 +254,7 @@ static void spreadsheet_filter_panel_draw(const bContext *C, Panel *panel)
|
|||
break;
|
||||
case SPREADSHEET_VALUE_TYPE_UNKNOWN:
|
||||
case SPREADSHEET_VALUE_TYPE_QUATERNION:
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT4X4:
|
||||
uiItemL(layout, IFACE_("Unsupported column type"), ICON_ERROR);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ typedef enum eCustomDataType {
|
|||
CD_PROP_BYTE_COLOR = 17,
|
||||
CD_TANGENT = 18,
|
||||
CD_MDISPS = 19,
|
||||
/* CD_PREVIEW_MCOL = 20, */ /* UNUSED */
|
||||
CD_PROP_FLOAT4X4 = 20,
|
||||
/* CD_ID_MCOL = 21, */
|
||||
/* CD_TEXTURE_MLOOPCOL = 22, */ /* UNUSED */
|
||||
CD_CLOTH_ORCO = 23,
|
||||
|
@ -230,6 +230,7 @@ using eCustomDataMask = uint64_t;
|
|||
#define CD_MASK_PROP_INT8 (1ULL << CD_PROP_INT8)
|
||||
#define CD_MASK_PROP_INT32_2D (1ULL << CD_PROP_INT32_2D)
|
||||
#define CD_MASK_PROP_QUATERNION (1ULL << CD_PROP_QUATERNION)
|
||||
#define CD_MASK_PROP_FLOAT4X4 (1ULL << CD_PROP_FLOAT4X4)
|
||||
|
||||
/** Multi-resolution loop data. */
|
||||
#define CD_MASK_MULTIRES_GRIDS (CD_MASK_MDISPS | CD_GRID_PAINT_MASK)
|
||||
|
@ -241,7 +242,7 @@ using eCustomDataMask = uint64_t;
|
|||
#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_INT32_2D | CD_MASK_PROP_QUATERNION)
|
||||
CD_MASK_PROP_INT8 | CD_MASK_PROP_INT32_2D | CD_MASK_PROP_QUATERNION | CD_MASK_PROP_FLOAT4X4)
|
||||
|
||||
/* All color attributes */
|
||||
#define CD_MASK_COLOR_ALL (CD_MASK_PROP_COLOR | CD_MASK_PROP_BYTE_COLOR)
|
||||
|
|
|
@ -263,6 +263,7 @@ typedef enum eNodeSocketDatatype {
|
|||
SOCK_MATERIAL = 13,
|
||||
SOCK_ROTATION = 14,
|
||||
SOCK_MENU = 15,
|
||||
SOCK_MATRIX = 16,
|
||||
} eNodeSocketDatatype;
|
||||
|
||||
/** Socket shape. */
|
||||
|
|
|
@ -2037,6 +2037,7 @@ typedef enum eSpreadsheetColumnValueType {
|
|||
SPREADSHEET_VALUE_TYPE_INT8 = 9,
|
||||
SPREADSHEET_VALUE_TYPE_INT32_2D = 10,
|
||||
SPREADSHEET_VALUE_TYPE_QUATERNION = 11,
|
||||
SPREADSHEET_VALUE_TYPE_FLOAT4X4 = 12,
|
||||
} eSpreadsheetColumnValueType;
|
||||
|
||||
/**
|
||||
|
|
|
@ -716,12 +716,13 @@ typedef struct UserDef_Experimental {
|
|||
char use_extended_asset_browser;
|
||||
char use_sculpt_texture_paint;
|
||||
char use_grease_pencil_version3;
|
||||
char use_new_matrix_socket;
|
||||
char enable_overlay_next;
|
||||
char use_new_volume_nodes;
|
||||
char use_shader_node_previews;
|
||||
char use_extension_repos;
|
||||
|
||||
char _pad[4];
|
||||
char _pad[3];
|
||||
/** `makesdna` does not allow empty structs. */
|
||||
} UserDef_Experimental;
|
||||
|
||||
|
|
|
@ -49,6 +49,10 @@ typedef struct vec4i {
|
|||
typedef struct vec4f {
|
||||
float x, y, z, w;
|
||||
} vec4f;
|
||||
|
||||
typedef struct mat4x4f {
|
||||
float value[4][4];
|
||||
} mat4x4f;
|
||||
/*
|
||||
typedef struct vec4d {
|
||||
double x, y, z, w;
|
||||
|
|
|
@ -47,6 +47,7 @@ const EnumPropertyItem rna_enum_attribute_type_items[] = {
|
|||
{CD_PROP_INT8, "INT8", 0, "8-Bit Integer", "Smaller integer with a range from -128 to 127"},
|
||||
{CD_PROP_INT32_2D, "INT32_2D", 0, "2D Integer Vector", "32-bit signed integer vector"},
|
||||
{CD_PROP_QUATERNION, "QUATERNION", 0, "Quaternion", "Floating point quaternion rotation"},
|
||||
{CD_PROP_FLOAT4X4, "FLOAT4X4", 0, "4x4 Matrix", "Floating point matrix"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
|
@ -76,6 +77,7 @@ const EnumPropertyItem rna_enum_attribute_type_with_auto_items[] = {
|
|||
{CD_PROP_FLOAT2, "FLOAT2", 0, "2D Vector", "2D vector with floating-point values"},
|
||||
{CD_PROP_INT32_2D, "INT32_2D", 0, "2D Integer Vector", "32-bit signed integer vector"},
|
||||
{CD_PROP_QUATERNION, "QUATERNION", 0, "Quaternion", "Floating point quaternion rotation"},
|
||||
{CD_PROP_FLOAT4X4, "FLOAT4X4", 0, "4x4 Matrix", "Floating point matrix"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
|
@ -207,6 +209,8 @@ static StructRNA *srna_by_custom_data_layer_type(const eCustomDataType type)
|
|||
return &RNA_Int2Attribute;
|
||||
case CD_PROP_QUATERNION:
|
||||
return &RNA_QuaternionAttribute;
|
||||
case CD_PROP_FLOAT4X4:
|
||||
return &RNA_Float4x4Attribute;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1096,6 +1100,40 @@ static void rna_def_attribute_quaternion(BlenderRNA *brna)
|
|||
RNA_def_property_update(prop, 0, "rna_Attribute_update_data");
|
||||
}
|
||||
|
||||
static void rna_def_attribute_float4x4(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "Float4x4Attribute", "Attribute");
|
||||
RNA_def_struct_sdna(srna, "CustomDataLayer");
|
||||
RNA_def_struct_ui_text(
|
||||
srna, "4x4 Matrix Attribute", "Geometry attribute that stores a 4 by 4 float matrix");
|
||||
|
||||
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "Float4x4AttributeValue");
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
|
||||
RNA_def_property_collection_funcs(prop,
|
||||
"rna_Attribute_data_begin",
|
||||
"rna_iterator_array_next",
|
||||
"rna_iterator_array_end",
|
||||
"rna_iterator_array_get",
|
||||
"rna_Attribute_data_length",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
|
||||
srna = RNA_def_struct(brna, "Float4x4AttributeValue", nullptr);
|
||||
RNA_def_struct_sdna(srna, "mat4x4f");
|
||||
RNA_def_struct_ui_text(srna, "Matrix Attribute Value", "Matrix value in geometry attribute");
|
||||
|
||||
prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_ui_text(prop, "Value", "Matrix");
|
||||
RNA_def_property_float_sdna(prop, nullptr, "value");
|
||||
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
|
||||
RNA_def_property_update(prop, 0, "rna_Attribute_update_data");
|
||||
}
|
||||
|
||||
static void rna_def_attribute_float2(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
@ -1182,6 +1220,7 @@ static void rna_def_attribute(BlenderRNA *brna)
|
|||
rna_def_attribute_int(brna);
|
||||
rna_def_attribute_int2(brna);
|
||||
rna_def_attribute_quaternion(brna);
|
||||
rna_def_attribute_float4x4(brna);
|
||||
rna_def_attribute_string(brna);
|
||||
rna_def_attribute_bool(brna);
|
||||
rna_def_attribute_float2(brna);
|
||||
|
|
|
@ -25,6 +25,7 @@ const EnumPropertyItem rna_enum_node_socket_type_items[] = {
|
|||
{SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""},
|
||||
{SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
|
||||
{SOCK_ROTATION, "ROTATION", 0, "Rotation", ""},
|
||||
{SOCK_MATRIX, "MATRIX", 0, "Matrix", ""},
|
||||
{SOCK_STRING, "STRING", 0, "String", ""},
|
||||
{SOCK_RGBA, "RGBA", 0, "RGBA", ""},
|
||||
{SOCK_SHADER, "SHADER", 0, "Shader", ""},
|
||||
|
@ -1011,6 +1012,30 @@ static void rna_def_node_socket_interface_rotation(BlenderRNA *brna, const char
|
|||
rna_def_node_tree_interface_socket_builtin(srna);
|
||||
}
|
||||
|
||||
static void rna_def_node_socket_matrix(BlenderRNA *brna, const char *identifier)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
|
||||
RNA_def_struct_ui_text(srna, "Matrix Node Socket", "Matrix value socket of a node");
|
||||
RNA_def_struct_sdna(srna, "bNodeSocket");
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bNodeSocket", nullptr);
|
||||
}
|
||||
|
||||
static void rna_def_node_socket_interface_matrix(BlenderRNA *brna, const char *identifier)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
srna = RNA_def_struct(brna, identifier, "NodeTreeInterfaceSocket");
|
||||
RNA_def_struct_ui_text(srna, "Matrix Node Socket Interface", "Matrix value socket of a node");
|
||||
RNA_def_struct_sdna(srna, "bNodeTreeInterfaceSocket");
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bNodeTreeInterfaceSocket", nullptr);
|
||||
|
||||
rna_def_node_tree_interface_socket_builtin(srna);
|
||||
}
|
||||
|
||||
static void rna_def_node_socket_vector(BlenderRNA *brna,
|
||||
const char *identifier,
|
||||
PropertySubType subtype)
|
||||
|
@ -1528,6 +1553,7 @@ static const bNodeSocketStaticTypeInfo node_socket_subtypes[] = {
|
|||
{"NodeSocketIntFactor", "NodeTreeInterfaceSocketIntFactor", SOCK_INT, PROP_FACTOR},
|
||||
{"NodeSocketBool", "NodeTreeInterfaceSocketBool", SOCK_BOOLEAN, PROP_NONE},
|
||||
{"NodeSocketRotation", "NodeTreeInterfaceSocketRotation", SOCK_ROTATION, PROP_NONE},
|
||||
{"NodeSocketMatrix", "NodeTreeInterfaceSocketMatrix", SOCK_MATRIX, PROP_NONE},
|
||||
{"NodeSocketVector", "NodeTreeInterfaceSocketVector", SOCK_VECTOR, PROP_NONE},
|
||||
{"NodeSocketVectorTranslation",
|
||||
"NodeTreeInterfaceSocketVectorTranslation",
|
||||
|
@ -1577,6 +1603,9 @@ static void rna_def_node_socket_subtypes(BlenderRNA *brna)
|
|||
case SOCK_ROTATION:
|
||||
rna_def_node_socket_rotation(brna, identifier);
|
||||
break;
|
||||
case SOCK_MATRIX:
|
||||
rna_def_node_socket_matrix(brna, identifier);
|
||||
break;
|
||||
case SOCK_VECTOR:
|
||||
rna_def_node_socket_vector(brna, identifier, info.subtype);
|
||||
break;
|
||||
|
@ -1640,6 +1669,9 @@ void rna_def_node_socket_interface_subtypes(BlenderRNA *brna)
|
|||
case SOCK_ROTATION:
|
||||
rna_def_node_socket_interface_rotation(brna, identifier);
|
||||
break;
|
||||
case SOCK_MATRIX:
|
||||
rna_def_node_socket_interface_matrix(brna, identifier);
|
||||
break;
|
||||
case SOCK_VECTOR:
|
||||
rna_def_node_socket_interface_vector(brna, identifier, info.subtype);
|
||||
break;
|
||||
|
|
|
@ -77,6 +77,7 @@ const EnumPropertyItem rna_enum_node_socket_data_type_items[] = {
|
|||
{SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""},
|
||||
{SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
|
||||
{SOCK_ROTATION, "ROTATION", 0, "Rotation", ""},
|
||||
{SOCK_MATRIX, "MATRIX", 0, "Matrix", ""},
|
||||
{SOCK_STRING, "STRING", 0, "String", ""},
|
||||
{SOCK_MENU, "MENU", 0, "Menu", ""},
|
||||
{SOCK_RGBA, "RGBA", 0, "Color", ""},
|
||||
|
@ -1894,7 +1895,8 @@ static bool generic_attribute_type_supported(const EnumPropertyItem *item)
|
|||
CD_PROP_BOOL,
|
||||
CD_PROP_INT32,
|
||||
CD_PROP_BYTE_COLOR,
|
||||
CD_PROP_QUATERNION);
|
||||
CD_PROP_QUATERNION,
|
||||
CD_PROP_FLOAT4X4);
|
||||
}
|
||||
|
||||
static bool generic_attribute_type_supported_with_socket(const EnumPropertyItem *item)
|
||||
|
|
|
@ -7120,6 +7120,12 @@ static void rna_def_userdef_experimental(BlenderRNA *brna)
|
|||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_keyconfig_reload_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_new_matrix_socket", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "use_new_matrix_socket", 1);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Matrix Socket", "Enable the matrix socket type for geometry nodes");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_ui_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_viewport_debug", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "use_viewport_debug", 1);
|
||||
RNA_def_property_ui_text(prop,
|
||||
|
|
|
@ -824,7 +824,7 @@ static void check_property_socket_sync(const Object *ob, ModifierData *md)
|
|||
|
||||
IDProperty *property = IDP_GetPropertyFromGroup(nmd->settings.properties, socket->identifier);
|
||||
if (property == nullptr) {
|
||||
if (type == SOCK_GEOMETRY) {
|
||||
if (ELEM(type, SOCK_GEOMETRY, SOCK_MATRIX)) {
|
||||
geometry_socket_count++;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -87,8 +87,15 @@ class GeoNodeExecParams {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
static inline constexpr bool is_field_base_type_v =
|
||||
is_same_any_v<T, float, int, bool, ColorGeometry4f, float3, std::string, math::Quaternion>;
|
||||
static inline constexpr bool is_field_base_type_v = is_same_any_v<T,
|
||||
float,
|
||||
int,
|
||||
bool,
|
||||
ColorGeometry4f,
|
||||
float3,
|
||||
std::string,
|
||||
math::Quaternion,
|
||||
float4x4>;
|
||||
|
||||
template<typename T>
|
||||
static inline constexpr bool stored_as_SocketValueVariant_v =
|
||||
|
|
|
@ -158,6 +158,22 @@ class RotationBuilder : public SocketDeclarationBuilder<Rotation> {
|
|||
RotationBuilder &default_value(const math::EulerXYZ &value);
|
||||
};
|
||||
|
||||
class MatrixBuilder;
|
||||
|
||||
class Matrix : public SocketDeclaration {
|
||||
public:
|
||||
friend MatrixBuilder;
|
||||
|
||||
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> {};
|
||||
|
||||
class StringBuilder;
|
||||
|
||||
class String : public SocketDeclaration {
|
||||
|
|
|
@ -267,6 +267,7 @@ DefNode(FunctionNode, FN_NODE_AXIS_ANGLE_TO_ROTATION, 0, "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_COMBINE_TRANSFORM, 0, "COMBINE_TRANSFORM", CombineTransform, "Combine Transform", "")
|
||||
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", "")
|
||||
|
@ -276,7 +277,9 @@ DefNode(FunctionNode, FN_NODE_INPUT_INT, def_fn_input_int, "INPUT_INT", InputInt
|
|||
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_INVERT_MATRIX, 0, "INVERT_MATRIX", InvertMatrix, "Invert Matrix", "")
|
||||
DefNode(FunctionNode, FN_NODE_INVERT_ROTATION, 0, "INVERT_ROTATION", InvertRotation, "Invert Rotation", "")
|
||||
DefNode(FunctionNode, FN_NODE_MATRIX_MULTIPLY, 0, "MATRIX_MULTIPLY", MatrixMultiply, "Multiply Matrices", "")
|
||||
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", "")
|
||||
|
@ -286,8 +289,12 @@ DefNode(FunctionNode, FN_NODE_ROTATION_TO_AXIS_ANGLE, 0, "ROTATION_TO_AXIS_ANGLE
|
|||
DefNode(FunctionNode, FN_NODE_ROTATION_TO_EULER, 0, "ROTATION_TO_EULER", RotationToEuler, "Rotation to Euler", "")
|
||||
DefNode(FunctionNode, FN_NODE_SEPARATE_COLOR, 0, "SEPARATE_COLOR", SeparateColor, "Separate Color", "")
|
||||
DefNode(FunctionNode, FN_NODE_ROTATION_TO_QUATERNION, 0, "ROTATION_TO_QUATERNION", RotationToQuaternion, "Rotation to Quaternion", "")
|
||||
DefNode(FunctionNode, FN_NODE_SEPARATE_TRANSFORM, 0, "SEPARATE_TRANSFORM", SeparateTransform, "Separate Transform", "")
|
||||
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
|
||||
DefNode(FunctionNode, FN_NODE_TRANSFORM_POINT, 0, "TRANSFORM_POINT", TransformPoint, "Transform Point", "")
|
||||
DefNode(FunctionNode, FN_NODE_TRANSPOSE_MATRIX, 0, "TRANSPOSE_MATRIX", TransposeMatrix, "Transpose Matrix", "")
|
||||
DefNode(FunctionNode, FN_NODE_VALUE_TO_STRING, 0, "VALUE_TO_STRING", ValueToString, "Value to String", "")
|
||||
|
||||
DefNode(GeometryNode, GEO_NODE_ACCUMULATE_FIELD, 0, "ACCUMULATE_FIELD", AccumulateField, "Accumulate Field", "Add the values of an evaluated field together and output the running total for each element")
|
||||
|
|
|
@ -51,12 +51,16 @@ struct SimulationItemsAccessor {
|
|||
}
|
||||
static bool supports_socket_type(const eNodeSocketDatatype socket_type)
|
||||
{
|
||||
if (socket_type == SOCK_MATRIX) {
|
||||
return U.experimental.use_new_matrix_socket;
|
||||
}
|
||||
return ELEM(socket_type,
|
||||
SOCK_FLOAT,
|
||||
SOCK_VECTOR,
|
||||
SOCK_RGBA,
|
||||
SOCK_BOOLEAN,
|
||||
SOCK_ROTATION,
|
||||
SOCK_MATRIX,
|
||||
SOCK_INT,
|
||||
SOCK_STRING,
|
||||
SOCK_GEOMETRY);
|
||||
|
@ -115,12 +119,16 @@ struct RepeatItemsAccessor {
|
|||
}
|
||||
static bool supports_socket_type(const eNodeSocketDatatype socket_type)
|
||||
{
|
||||
if (socket_type == SOCK_MATRIX) {
|
||||
return U.experimental.use_new_matrix_socket;
|
||||
}
|
||||
return ELEM(socket_type,
|
||||
SOCK_FLOAT,
|
||||
SOCK_VECTOR,
|
||||
SOCK_RGBA,
|
||||
SOCK_BOOLEAN,
|
||||
SOCK_ROTATION,
|
||||
SOCK_MATRIX,
|
||||
SOCK_INT,
|
||||
SOCK_STRING,
|
||||
SOCK_GEOMETRY,
|
||||
|
|
|
@ -31,7 +31,10 @@ set(SRC
|
|||
nodes/node_fn_input_special_characters.cc
|
||||
nodes/node_fn_input_string.cc
|
||||
nodes/node_fn_input_vector.cc
|
||||
nodes/node_fn_invert_matrix.cc
|
||||
nodes/node_fn_invert_rotation.cc
|
||||
nodes/node_fn_combine_transform.cc
|
||||
nodes/node_fn_matrix_multiply.cc
|
||||
nodes/node_fn_quaternion_to_rotation.cc
|
||||
nodes/node_fn_random_value.cc
|
||||
nodes/node_fn_replace_string.cc
|
||||
|
@ -42,8 +45,12 @@ set(SRC
|
|||
nodes/node_fn_rotation_to_euler.cc
|
||||
nodes/node_fn_rotation_to_quaternion.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
|
||||
nodes/node_fn_transform_point.cc
|
||||
nodes/node_fn_transpose_matrix.cc
|
||||
nodes/node_fn_value_to_string.cc
|
||||
|
||||
node_function_util.cc
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
#include "BLI_math_rotation.hh"
|
||||
|
||||
#include "NOD_socket_search_link.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");
|
||||
}
|
||||
|
||||
static void search_link_ops(GatherLinkSearchOpParams ¶ms)
|
||||
{
|
||||
if (U.experimental.use_new_matrix_socket) {
|
||||
nodes::search_link_ops_for_basic_node(params);
|
||||
}
|
||||
}
|
||||
|
||||
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]); });
|
||||
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 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]); });
|
||||
}
|
||||
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.gather_link_search_ops = search_link_ops;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_combine_transform_cc
|
|
@ -0,0 +1,45 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
|
||||
#include "NOD_socket_search_link.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_invert_matrix_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Matrix>("Matrix");
|
||||
b.add_output<decl::Matrix>("Matrix");
|
||||
}
|
||||
|
||||
static void search_link_ops(GatherLinkSearchOpParams ¶ms)
|
||||
{
|
||||
if (U.experimental.use_new_matrix_socket) {
|
||||
nodes::search_link_ops_for_basic_node(params);
|
||||
}
|
||||
}
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI1_SO<float4x4, float4x4>(
|
||||
"Invert Matrix", [](float4x4 matrix) { return math::invert(matrix); });
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(&ntype, FN_NODE_INVERT_MATRIX, "Invert Matrix", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.gather_link_search_ops = search_link_ops;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_invert_matrix_cc
|
|
@ -0,0 +1,46 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
|
||||
#include "NOD_socket_search_link.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_matrix_multiply_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Matrix>("Matrix");
|
||||
b.add_input<decl::Matrix>("Matrix", "Matrix_001");
|
||||
b.add_output<decl::Matrix>("Matrix");
|
||||
}
|
||||
|
||||
static void search_link_ops(GatherLinkSearchOpParams ¶ms)
|
||||
{
|
||||
if (U.experimental.use_new_matrix_socket) {
|
||||
nodes::search_link_ops_for_basic_node(params);
|
||||
}
|
||||
}
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI2_SO<float4x4, float4x4, float4x4>(
|
||||
"Multiply Matrices", [](float4x4 a, float4x4 b) { return a * b; });
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(&ntype, FN_NODE_MATRIX_MULTIPLY, "Multiply Matrices", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.gather_link_search_ops = search_link_ops;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_matrix_multiply_cc
|
|
@ -0,0 +1,92 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
#include "BLI_math_rotation.hh"
|
||||
|
||||
#include "NOD_socket_search_link.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);
|
||||
};
|
||||
|
||||
static void search_link_ops(GatherLinkSearchOpParams ¶ms)
|
||||
{
|
||||
if (U.experimental.use_new_matrix_socket) {
|
||||
nodes::search_link_ops_for_basic_node(params);
|
||||
}
|
||||
}
|
||||
|
||||
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.gather_link_search_ops = search_link_ops;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_separate_transform_cc
|
|
@ -0,0 +1,49 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
|
||||
#include "NOD_socket_search_link.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_transform_direction_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Vector>("Direction").subtype(PROP_XYZ);
|
||||
b.add_input<decl::Matrix>("Transform");
|
||||
b.add_output<decl::Vector>("Direction").subtype(PROP_XYZ);
|
||||
}
|
||||
|
||||
static void search_link_ops(GatherLinkSearchOpParams ¶ms)
|
||||
{
|
||||
if (U.experimental.use_new_matrix_socket) {
|
||||
nodes::search_link_ops_for_basic_node(params);
|
||||
}
|
||||
}
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI2_SO<float3, float4x4, float3>(
|
||||
"Transform Direction", [](float3 direction, float4x4 matrix) {
|
||||
return math::transform_direction(matrix, direction);
|
||||
});
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(
|
||||
&ntype, FN_NODE_TRANSFORM_DIRECTION, "Transform Direction", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.gather_link_search_ops = search_link_ops;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_transform_direction_cc
|
|
@ -0,0 +1,47 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
|
||||
#include "NOD_socket_search_link.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_transform_point_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Vector>("Vector").subtype(PROP_XYZ);
|
||||
b.add_input<decl::Matrix>("Transform");
|
||||
b.add_output<decl::Vector>("Vector").subtype(PROP_XYZ);
|
||||
}
|
||||
|
||||
static void search_link_ops(GatherLinkSearchOpParams ¶ms)
|
||||
{
|
||||
if (U.experimental.use_new_matrix_socket) {
|
||||
nodes::search_link_ops_for_basic_node(params);
|
||||
}
|
||||
}
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI2_SO<float3, float4x4, float3>(
|
||||
"Transform Point",
|
||||
[](float3 point, float4x4 matrix) { return math::transform_point(matrix, point); });
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(&ntype, FN_NODE_TRANSFORM_POINT, "Transform Point", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.gather_link_search_ops = search_link_ops;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_transform_point_cc
|
|
@ -0,0 +1,45 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
|
||||
#include "NOD_socket_search_link.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_transpose_matrix_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Matrix>("Matrix");
|
||||
b.add_output<decl::Matrix>("Matrix");
|
||||
}
|
||||
|
||||
static void search_link_ops(GatherLinkSearchOpParams ¶ms)
|
||||
{
|
||||
if (U.experimental.use_new_matrix_socket) {
|
||||
nodes::search_link_ops_for_basic_node(params);
|
||||
}
|
||||
}
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI1_SO<float4x4, float4x4>(
|
||||
"Transpose Matrix", [](float4x4 matrix) { return math::transpose(matrix); });
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(&ntype, FN_NODE_TRANSPOSE_MATRIX, "Transpose Matrix", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.gather_link_search_ops = search_link_ops;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_transpose_matrix_cc
|
|
@ -96,6 +96,15 @@ static bool geometry_node_tree_validate_link(eNodeSocketDatatype type_a,
|
|||
/* Floats and vectors implicitly convert to rotations. */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Support implicit conversions between matrices and rotations. */
|
||||
if (type_a == SOCK_MATRIX && type_b == SOCK_ROTATION) {
|
||||
return true;
|
||||
}
|
||||
if (type_a == SOCK_ROTATION && type_b == SOCK_MATRIX) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type_a == SOCK_ROTATION && type_b == SOCK_VECTOR) {
|
||||
/* Rotations implicitly convert to vectors. */
|
||||
return true;
|
||||
|
@ -106,12 +115,16 @@ static bool geometry_node_tree_validate_link(eNodeSocketDatatype type_a,
|
|||
static bool geometry_node_tree_socket_type_valid(bNodeTreeType * /*treetype*/,
|
||||
bNodeSocketType *socket_type)
|
||||
{
|
||||
if (socket_type->type == SOCK_MATRIX) {
|
||||
return U.experimental.use_new_matrix_socket;
|
||||
}
|
||||
return blender::bke::nodeIsStaticSocketType(socket_type) && ELEM(socket_type->type,
|
||||
SOCK_FLOAT,
|
||||
SOCK_VECTOR,
|
||||
SOCK_RGBA,
|
||||
SOCK_BOOLEAN,
|
||||
SOCK_ROTATION,
|
||||
SOCK_MATRIX,
|
||||
SOCK_INT,
|
||||
SOCK_STRING,
|
||||
SOCK_OBJECT,
|
||||
|
|
|
@ -50,6 +50,9 @@ const EnumPropertyItem *attribute_type_type_with_socket_fn(bContext * /*C*/,
|
|||
|
||||
bool generic_attribute_type_supported(const EnumPropertyItem &item)
|
||||
{
|
||||
if (item.value == SOCK_MATRIX) {
|
||||
return U.experimental.use_new_matrix_socket;
|
||||
}
|
||||
return ELEM(item.value,
|
||||
CD_PROP_FLOAT,
|
||||
CD_PROP_FLOAT2,
|
||||
|
@ -58,7 +61,8 @@ bool generic_attribute_type_supported(const EnumPropertyItem &item)
|
|||
CD_PROP_BOOL,
|
||||
CD_PROP_INT32,
|
||||
CD_PROP_BYTE_COLOR,
|
||||
CD_PROP_QUATERNION);
|
||||
CD_PROP_QUATERNION,
|
||||
CD_PROP_FLOAT4X4);
|
||||
}
|
||||
|
||||
const EnumPropertyItem *domain_experimental_grease_pencil_version3_fn(bContext * /*C*/,
|
||||
|
|
|
@ -88,6 +88,10 @@ static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms)
|
|||
/* Don't implement quaternion blurring for now. */
|
||||
return;
|
||||
}
|
||||
if (fixed_data_type == CD_PROP_FLOAT4X4) {
|
||||
/* Don't implement matrix blurring for now. */
|
||||
return;
|
||||
}
|
||||
if (fixed_data_type == CD_PROP_BOOL) {
|
||||
/* This node does not support boolean sockets, use integer instead. */
|
||||
fixed_data_type = CD_PROP_INT32;
|
||||
|
|
|
@ -290,11 +290,15 @@ static void node_rna(StructRNA *srna)
|
|||
*r_free = true;
|
||||
return enum_items_filter(rna_enum_node_socket_data_type_items,
|
||||
[](const EnumPropertyItem &item) -> bool {
|
||||
if (item.value == SOCK_MATRIX) {
|
||||
return U.experimental.use_new_matrix_socket;
|
||||
}
|
||||
return ELEM(item.value,
|
||||
SOCK_FLOAT,
|
||||
SOCK_INT,
|
||||
SOCK_BOOLEAN,
|
||||
SOCK_ROTATION,
|
||||
SOCK_MATRIX,
|
||||
SOCK_VECTOR,
|
||||
SOCK_STRING,
|
||||
SOCK_RGBA,
|
||||
|
|
|
@ -427,9 +427,9 @@ class LazyFunctionForSimulationOutputNode final : public LazyFunction {
|
|||
Span<NodeSimulationItem> simulation_items_;
|
||||
int skip_input_index_;
|
||||
/**
|
||||
* Start index of the simulation state inputs that are used when the simulation is skipped. Those
|
||||
* inputs are linked directly to the simulation input node. Those inputs only exist internally,
|
||||
* but not in the UI.
|
||||
* Start index of the simulation state inputs that are used when the simulation is skipped.
|
||||
* Those inputs are linked directly to the simulation input node. Those inputs only exist
|
||||
* internally, but not in the UI.
|
||||
*/
|
||||
int skip_inputs_offset_;
|
||||
/**
|
||||
|
@ -648,8 +648,8 @@ class LazyFunctionForSimulationOutputNode final : public LazyFunction {
|
|||
}
|
||||
const bool skip = skip_variant->get<bool>();
|
||||
|
||||
/* Instead of outputting the values directly, convert them to a bake state and then back. This
|
||||
* ensures that some geometry processing happens on the data consistently (e.g. removing
|
||||
/* Instead of outputting the values directly, convert them to a bake state and then back.
|
||||
* This ensures that some geometry processing happens on the data consistently (e.g. removing
|
||||
* anonymous attributes). */
|
||||
std::optional<bke::bake::BakeState> bake_state = this->get_bake_state_from_inputs(
|
||||
params, data_block_map, skip);
|
||||
|
@ -945,7 +945,8 @@ void mix_baked_data_item(const eNodeSocketDatatype socket_type,
|
|||
case SOCK_INT:
|
||||
case SOCK_BOOLEAN:
|
||||
case SOCK_ROTATION:
|
||||
case SOCK_RGBA: {
|
||||
case SOCK_RGBA:
|
||||
case SOCK_MATRIX: {
|
||||
const CPPType &type = node_geo_simulation_cc::get_simulation_item_cpp_type(socket_type);
|
||||
SocketValueVariant prev_value_variant = *static_cast<const SocketValueVariant *>(prev);
|
||||
SocketValueVariant next_value_variant = *static_cast<const SocketValueVariant *>(next);
|
||||
|
|
|
@ -222,11 +222,15 @@ static void node_rna(StructRNA *srna)
|
|||
*r_free = true;
|
||||
return enum_items_filter(rna_enum_node_socket_data_type_items,
|
||||
[](const EnumPropertyItem &item) -> bool {
|
||||
if (item.value == SOCK_MATRIX) {
|
||||
return U.experimental.use_new_matrix_socket;
|
||||
}
|
||||
return ELEM(item.value,
|
||||
SOCK_FLOAT,
|
||||
SOCK_INT,
|
||||
SOCK_BOOLEAN,
|
||||
SOCK_ROTATION,
|
||||
SOCK_MATRIX,
|
||||
SOCK_VECTOR,
|
||||
SOCK_STRING,
|
||||
SOCK_RGBA,
|
||||
|
|
|
@ -93,7 +93,6 @@ static bool node_needs_own_transform_relation(const bNode &node)
|
|||
node.storage);
|
||||
return storage.transform_space == GEO_NODE_TRANSFORM_SPACE_RELATIVE;
|
||||
}
|
||||
|
||||
if (node.type == GEO_NODE_SELF_OBJECT) {
|
||||
return true;
|
||||
}
|
||||
|
@ -346,6 +345,7 @@ std::unique_ptr<IDProperty, bke::idprop::IDPropertyDeleter> id_property_create_f
|
|||
socket.socket_data);
|
||||
return bke::idprop::create(identifier, reinterpret_cast<ID *>(value->value));
|
||||
}
|
||||
case SOCK_MATRIX:
|
||||
case SOCK_CUSTOM:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_SHADER:
|
||||
|
@ -387,6 +387,7 @@ bool id_property_type_matches_socket(const bNodeTreeInterfaceSocket &socket,
|
|||
case SOCK_MATERIAL:
|
||||
return property.type == IDP_ID;
|
||||
case SOCK_CUSTOM:
|
||||
case SOCK_MATRIX:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_SHADER:
|
||||
return false;
|
||||
|
@ -674,12 +675,15 @@ static Vector<OutputAttributeToStore> compute_attributes_to_store(
|
|||
for (const OutputAttributeInfo &output_info : outputs_info) {
|
||||
const CPPType &type = output_info.field.cpp_type();
|
||||
const bke::AttributeValidator validator = attributes.lookup_validator(output_info.name);
|
||||
|
||||
OutputAttributeToStore store{
|
||||
component_type,
|
||||
domain,
|
||||
output_info.name,
|
||||
GMutableSpan{
|
||||
type, MEM_malloc_arrayN(domain_size, type.size(), __func__), domain_size}};
|
||||
type,
|
||||
MEM_mallocN_aligned(type.size() * domain_size, type.alignment(), __func__),
|
||||
domain_size}};
|
||||
fn::GField field = validator.validate_field_if_necessary(output_info.field);
|
||||
field_evaluator.add_with_destination(std::move(field), store.data);
|
||||
attributes_to_store.append(store);
|
||||
|
@ -868,7 +872,7 @@ void update_input_properties_from_node_tree(const bNodeTree &tree,
|
|||
if (new_prop == nullptr) {
|
||||
/* Out of the set of supported input sockets, only
|
||||
* geometry sockets aren't added to the modifier. */
|
||||
BLI_assert(socket_type == SOCK_GEOMETRY);
|
||||
BLI_assert(ELEM(socket_type, SOCK_GEOMETRY, SOCK_MATRIX));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -245,6 +245,11 @@ static SocketDeclarationPtr declaration_for_interface_socket(
|
|||
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_INT: {
|
||||
const auto &value = node_interface::get_socket_data_as<bNodeSocketValueInt>(io_socket);
|
||||
std::unique_ptr<decl::Int> decl = std::make_unique<decl::Int>();
|
||||
|
|
|
@ -414,6 +414,8 @@ std::unique_ptr<SocketDeclaration> make_declaration_for_socket_type(
|
|||
return std::make_unique<decl::Bool>();
|
||||
case SOCK_ROTATION:
|
||||
return std::make_unique<decl::Rotation>();
|
||||
case SOCK_MATRIX:
|
||||
return std::make_unique<decl::Matrix>();
|
||||
case SOCK_INT:
|
||||
return std::make_unique<decl::Int>();
|
||||
case SOCK_STRING:
|
||||
|
@ -449,6 +451,8 @@ BaseSocketDeclarationBuilder &NodeDeclarationBuilder::add_input(
|
|||
return this->add_input<decl::Bool>(name, identifier);
|
||||
case SOCK_ROTATION:
|
||||
return this->add_input<decl::Rotation>(name, identifier);
|
||||
case SOCK_MATRIX:
|
||||
return this->add_input<decl::Matrix>(name, identifier);
|
||||
case SOCK_INT:
|
||||
return this->add_input<decl::Int>(name, identifier);
|
||||
case SOCK_STRING:
|
||||
|
@ -492,6 +496,8 @@ BaseSocketDeclarationBuilder &NodeDeclarationBuilder::add_output(
|
|||
return this->add_output<decl::Bool>(name, identifier);
|
||||
case SOCK_ROTATION:
|
||||
return this->add_output<decl::Rotation>(name, identifier);
|
||||
case SOCK_MATRIX:
|
||||
return this->add_output<decl::Matrix>(name, identifier);
|
||||
case SOCK_INT:
|
||||
return this->add_output<decl::Int>(name, identifier);
|
||||
case SOCK_STRING:
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include "BLI_color.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_euler.hh"
|
||||
#include "BLI_math_matrix.h"
|
||||
#include "BLI_math_matrix.hh"
|
||||
#include "BLI_math_quaternion_types.hh"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
@ -298,6 +300,9 @@ static std::optional<eNodeSocketDatatype> decl_to_data_type(const SocketDeclarat
|
|||
else if (dynamic_cast<const decl::Rotation *>(&socket_decl)) {
|
||||
return SOCK_ROTATION;
|
||||
}
|
||||
else if (dynamic_cast<const decl::Matrix *>(&socket_decl)) {
|
||||
return SOCK_MATRIX;
|
||||
}
|
||||
else if (dynamic_cast<const decl::String *>(&socket_decl)) {
|
||||
return SOCK_STRING;
|
||||
}
|
||||
|
@ -554,7 +559,8 @@ bool socket_type_supports_fields(const eNodeSocketDatatype socket_type)
|
|||
SOCK_BOOLEAN,
|
||||
SOCK_INT,
|
||||
SOCK_ROTATION,
|
||||
SOCK_MENU);
|
||||
SOCK_MENU,
|
||||
SOCK_MATRIX);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes
|
||||
|
@ -699,6 +705,7 @@ void node_socket_init_default_value_data(eNodeSocketDatatype datatype, int subty
|
|||
|
||||
case SOCK_CUSTOM:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_MATRIX:
|
||||
case SOCK_SHADER:
|
||||
break;
|
||||
}
|
||||
|
@ -797,6 +804,7 @@ void node_socket_copy_default_value_data(eNodeSocketDatatype datatype, void *to,
|
|||
|
||||
case SOCK_CUSTOM:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_MATRIX:
|
||||
case SOCK_SHADER:
|
||||
break;
|
||||
}
|
||||
|
@ -978,6 +986,22 @@ static bNodeSocketType *make_socket_type_rotation()
|
|||
return socktype;
|
||||
}
|
||||
|
||||
static bNodeSocketType *make_socket_type_matrix()
|
||||
{
|
||||
bNodeSocketType *socktype = make_standard_socket_type(SOCK_MATRIX, PROP_NONE);
|
||||
socktype->base_cpp_type = &blender::CPPType::get<float4x4>();
|
||||
socktype->get_base_cpp_value = [](const void * /*socket_value*/, void *r_value) {
|
||||
*static_cast<float4x4 *>(r_value) = float4x4::identity();
|
||||
};
|
||||
socktype->geometry_nodes_cpp_type = &blender::CPPType::get<SocketValueVariant>();
|
||||
socktype->get_geometry_nodes_cpp_value = [](const void * /*socket_value*/, void *r_value) {
|
||||
new (r_value) SocketValueVariant(float4x4::identity());
|
||||
};
|
||||
static SocketValueVariant default_value{float4x4::identity()};
|
||||
socktype->geometry_nodes_default_cpp_value = &default_value;
|
||||
return socktype;
|
||||
}
|
||||
|
||||
static bNodeSocketType *make_socket_type_float(PropertySubType subtype)
|
||||
{
|
||||
bNodeSocketType *socktype = make_standard_socket_type(SOCK_FLOAT, subtype);
|
||||
|
@ -1172,6 +1196,7 @@ void register_standard_node_socket_types()
|
|||
|
||||
nodeRegisterSocketType(make_socket_type_bool());
|
||||
nodeRegisterSocketType(make_socket_type_rotation());
|
||||
nodeRegisterSocketType(make_socket_type_matrix());
|
||||
|
||||
nodeRegisterSocketType(make_socket_type_vector(PROP_NONE));
|
||||
nodeRegisterSocketType(make_socket_type_vector(PROP_TRANSLATION));
|
||||
|
|
|
@ -417,9 +417,9 @@ bool Rotation::can_connect(const bNodeSocket &socket) const
|
|||
return false;
|
||||
}
|
||||
if (this->in_out == SOCK_IN) {
|
||||
return ELEM(socket.type, SOCK_ROTATION, SOCK_FLOAT, SOCK_VECTOR);
|
||||
return ELEM(socket.type, SOCK_ROTATION, SOCK_FLOAT, SOCK_VECTOR, SOCK_MATRIX);
|
||||
}
|
||||
return ELEM(socket.type, SOCK_ROTATION, SOCK_VECTOR);
|
||||
return ELEM(socket.type, SOCK_ROTATION, SOCK_VECTOR, SOCK_MATRIX);
|
||||
}
|
||||
|
||||
bNodeSocket &Rotation::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
|
||||
|
@ -434,6 +434,57 @@ bNodeSocket &Rotation::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocke
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #Matrix
|
||||
* \{ */
|
||||
|
||||
bNodeSocket &Matrix::build(bNodeTree &ntree, bNode &node) const
|
||||
{
|
||||
bNodeSocket &socket = *nodeAddStaticSocket(&ntree,
|
||||
&node,
|
||||
this->in_out,
|
||||
SOCK_MATRIX,
|
||||
PROP_NONE,
|
||||
this->identifier.c_str(),
|
||||
this->name.c_str());
|
||||
this->set_common_flags(socket);
|
||||
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
|
||||
{
|
||||
if (!sockets_can_connect(*this, socket)) {
|
||||
return false;
|
||||
}
|
||||
if (this->in_out == SOCK_IN) {
|
||||
return ELEM(socket.type, SOCK_MATRIX, SOCK_FLOAT, SOCK_VECTOR, SOCK_MATRIX);
|
||||
}
|
||||
return ELEM(socket.type, SOCK_MATRIX, SOCK_VECTOR, SOCK_MATRIX);
|
||||
}
|
||||
|
||||
bNodeSocket &Matrix::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
|
||||
{
|
||||
if (socket.type != SOCK_MATRIX) {
|
||||
BLI_assert(socket.in_out == this->in_out);
|
||||
return this->build(ntree, node);
|
||||
}
|
||||
this->set_common_flags(socket);
|
||||
return socket;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #String
|
||||
* \{ */
|
||||
|
|
Loading…
Reference in New Issue
Some missing renames.