From 4a52f75e5867ddce7b071ce25ef1e09454e2bf59 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 15 May 2023 17:09:57 -0400 Subject: [PATCH 1/4] Nodes: Add rotation socket type --- source/blender/blenkernel/intern/node.cc | 16 ++++ .../intern/node_tree_field_inferencing.cc | 2 +- source/blender/editors/space_node/drawnode.cc | 7 ++ .../node_geometry_attribute_search.cc | 1 + .../editors/space_node/node_relationships.cc | 4 + .../editors/space_node/node_templates.cc | 4 + source/blender/makesdna/DNA_node_types.h | 10 +++ source/blender/makesrna/intern/rna_nodetree.c | 73 ++++++++++++++++++- source/blender/nodes/NOD_geometry_exec.hh | 4 +- .../blender/nodes/NOD_socket_declarations.hh | 34 +++++++++ .../nodes/geometry/node_geometry_tree.cc | 1 + source/blender/nodes/intern/node_common.cc | 8 ++ source/blender/nodes/intern/node_socket.cc | 32 ++++++++ .../nodes/intern/node_socket_declarations.cc | 55 ++++++++++++++ 14 files changed, 248 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 39d3d2b37eb..4ec01d820aa 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -329,6 +329,7 @@ static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket case SOCK_VECTOR: case SOCK_RGBA: case SOCK_BOOLEAN: + case SOCK_ROTATION: case SOCK_INT: case SOCK_STRING: case SOCK_CUSTOM: @@ -475,6 +476,9 @@ static void write_node_socket_default_value(BlendWriter *writer, bNodeSocket *so case SOCK_MATERIAL: BLO_write_struct(writer, bNodeSocketValueMaterial, sock->default_value); break; + case SOCK_ROTATION: + BLO_write_struct(writer, bNodeSocketValueRotation, sock->default_value); + break; case SOCK_CUSTOM: /* Custom node sockets where default_value is defined uses custom properties for storage. */ break; @@ -919,6 +923,7 @@ static void lib_link_node_socket(BlendLibReader *reader, ID *self_id, bNodeSocke case SOCK_VECTOR: case SOCK_RGBA: case SOCK_BOOLEAN: + case SOCK_ROTATION: case SOCK_INT: case SOCK_STRING: case SOCK_CUSTOM: @@ -1011,6 +1016,7 @@ static void expand_node_socket(BlendExpander *expander, bNodeSocket *sock) case SOCK_VECTOR: case SOCK_RGBA: case SOCK_BOOLEAN: + case SOCK_ROTATION: case SOCK_INT: case SOCK_STRING: case SOCK_CUSTOM: @@ -1699,6 +1705,7 @@ static void socket_id_user_increment(bNodeSocket *sock) case SOCK_VECTOR: case SOCK_RGBA: case SOCK_BOOLEAN: + case SOCK_ROTATION: case SOCK_INT: case SOCK_STRING: case SOCK_CUSTOM: @@ -1744,6 +1751,7 @@ static bool socket_id_user_decrement(bNodeSocket *sock) case SOCK_VECTOR: case SOCK_RGBA: case SOCK_BOOLEAN: + case SOCK_ROTATION: case SOCK_INT: case SOCK_STRING: case SOCK_CUSTOM: @@ -1797,6 +1805,7 @@ void nodeModifySocketType(bNodeTree *ntree, case SOCK_RGBA: case SOCK_SHADER: case SOCK_BOOLEAN: + case SOCK_ROTATION: case SOCK_CUSTOM: case SOCK_OBJECT: case SOCK_IMAGE: @@ -1900,6 +1909,8 @@ const char *nodeStaticSocketType(const int type, const int subtype) } case SOCK_BOOLEAN: return "NodeSocketBool"; + case SOCK_ROTATION: + return "NodeSocketRotation"; case SOCK_VECTOR: switch (PropertySubType(subtype)) { case PROP_TRANSLATION: @@ -1979,6 +1990,8 @@ const char *nodeStaticSocketInterfaceType(const int type, const int subtype) } case SOCK_BOOLEAN: return "NodeSocketInterfaceBool"; + case SOCK_ROTATION: + return "NodeSocketInterfaceRotation"; case SOCK_VECTOR: switch (PropertySubType(subtype)) { case PROP_TRANSLATION: @@ -2030,6 +2043,8 @@ const char *nodeStaticSocketLabel(const int type, const int /*subtype*/) return "Integer"; case SOCK_BOOLEAN: return "Boolean"; + case SOCK_ROTATION: + return "Rotation"; case SOCK_VECTOR: return "Vector"; case SOCK_RGBA: @@ -2570,6 +2585,7 @@ static void *socket_value_storage(bNodeSocket &socket) case SOCK_MATERIAL: return &socket.default_value_typed()->value; case SOCK_STRING: + case SOCK_ROTATION: /* We don't want do this now! */ return nullptr; case SOCK_CUSTOM: diff --git a/source/blender/blenkernel/intern/node_tree_field_inferencing.cc b/source/blender/blenkernel/intern/node_tree_field_inferencing.cc index 9dc9549c1de..05293547674 100644 --- a/source/blender/blenkernel/intern/node_tree_field_inferencing.cc +++ b/source/blender/blenkernel/intern/node_tree_field_inferencing.cc @@ -22,7 +22,7 @@ using nodes::SocketDeclaration; static bool is_field_socket_type(eNodeSocketDatatype type) { - return ELEM(type, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, SOCK_VECTOR, SOCK_RGBA); + return ELEM(type, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, SOCK_VECTOR, SOCK_RGBA, SOCK_ROTATION); } static bool is_field_socket_type(const bNodeSocket &socket) diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index c0794325b9d..1147aa029ef 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -1205,6 +1205,7 @@ static const float std_node_socket_colors[][4] = { {0.96, 0.96, 0.96, 1.0}, /* SOCK_COLLECTION */ {0.62, 0.31, 0.64, 1.0}, /* SOCK_TEXTURE */ {0.92, 0.46, 0.51, 1.0}, /* SOCK_MATERIAL */ + {0.92, 0.46, 0.7, 1.0}, /* SOCK_ROTATION */ }; /* common color callbacks for standard types */ @@ -1327,6 +1328,11 @@ static void std_node_socket_draw( } } break; + case SOCK_ROTATION: { + uiLayout *column = uiLayoutColumn(layout, true); + uiItemR(column, ptr, "default_value", DEFAULT_FLAGS, text, ICON_NONE); + break; + } case SOCK_RGBA: { if (text[0] == '\0') { uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, "", 0); @@ -1458,6 +1464,7 @@ static void std_node_socket_interface_draw(bContext * /*C*/, uiLayout *layout, P break; } case SOCK_BOOLEAN: + case SOCK_ROTATION: case SOCK_RGBA: case SOCK_STRING: case SOCK_OBJECT: diff --git a/source/blender/editors/space_node/node_geometry_attribute_search.cc b/source/blender/editors/space_node/node_geometry_attribute_search.cc index c1b84d813e5..6192db8b44b 100644 --- a/source/blender/editors/space_node/node_geometry_attribute_search.cc +++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc @@ -139,6 +139,7 @@ static eCustomDataType data_type_in_attribute_input_node(const eCustomDataType t case CD_PROP_FLOAT3: case CD_PROP_COLOR: case CD_PROP_BOOL: + case CD_PROP_QUATERNION: return type; case CD_PROP_BYTE_COLOR: return CD_PROP_COLOR; diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index 0b4c06835e4..e1f271d0df9 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -432,6 +432,7 @@ static bool socket_can_be_viewed(const bNodeSocket &socket) SOCK_VECTOR, SOCK_INT, SOCK_BOOLEAN, + SOCK_ROTATION, SOCK_RGBA); } @@ -448,6 +449,8 @@ static eCustomDataType socket_type_to_custom_data_type(const eNodeSocketDatatype return CD_PROP_BOOL; case SOCK_RGBA: return CD_PROP_COLOR; + case SOCK_ROTATION: + return CD_PROP_QUATERNION; default: /* Fallback. */ return CD_AUTO_FROM_NAME; @@ -2238,6 +2241,7 @@ static int get_main_socket_priority(const bNodeSocket *socket) case SOCK_SHADER: case SOCK_OBJECT: case SOCK_IMAGE: + case SOCK_ROTATION: case SOCK_GEOMETRY: case SOCK_COLLECTION: case SOCK_TEXTURE: diff --git a/source/blender/editors/space_node/node_templates.cc b/source/blender/editors/space_node/node_templates.cc index 488d6e719c6..d4906c94c05 100644 --- a/source/blender/editors/space_node/node_templates.cc +++ b/source/blender/editors/space_node/node_templates.cc @@ -391,6 +391,9 @@ static Vector ui_node_link_items(NodeLinkArg *arg, else if (dynamic_cast(&socket_decl)) { item.socket_type = SOCK_RGBA; } + else if (dynamic_cast(&socket_decl)) { + item.socket_type = SOCK_ROTATION; + } else if (dynamic_cast(&socket_decl)) { item.socket_type = SOCK_STRING; } @@ -873,6 +876,7 @@ static void ui_node_draw_input( ATTR_FALLTHROUGH; case SOCK_FLOAT: case SOCK_INT: + case SOCK_ROTATION: case SOCK_BOOLEAN: case SOCK_RGBA: uiItemR(sub, &inputptr, "default_value", 0, "", ICON_NONE); diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index ce662dbeb71..c5627250e06 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -238,6 +238,7 @@ typedef enum eNodeSocketDatatype { SOCK_COLLECTION = 11, SOCK_TEXTURE = 12, SOCK_MATERIAL = 13, + SOCK_ROTATION = 14, } eNodeSocketDatatype; /** Socket shape. */ @@ -724,6 +725,10 @@ typedef struct bNodeSocketValueVector { float min, max; } bNodeSocketValueVector; +typedef struct bNodeSocketValueRotation { + float value_euler[3]; +} bNodeSocketValueRotation; + typedef struct bNodeSocketValueRGBA { float value[4]; } bNodeSocketValueRGBA; @@ -2461,3 +2466,8 @@ typedef enum NodeCombSepColorMode { NODE_COMBSEP_COLOR_HSV = 1, NODE_COMBSEP_COLOR_HSL = 2, } NodeCombSepColorMode; + +typedef enum NodeCombineSeparateRotatioNMode { + NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ = 0, + NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE = 1, +} NodeCombineSeparateRotatioNMode; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index a242e512dd7..cc836dda3d5 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -68,6 +68,7 @@ static const EnumPropertyItem node_socket_data_type_items[] = { {SOCK_INT, "INT", 0, "Integer", ""}, {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""}, {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, + {SOCK_ROTATION, "ROTATION", 0, "Rotation", ""}, {SOCK_STRING, "STRING", 0, "String", ""}, {SOCK_RGBA, "RGBA", 0, "Color", ""}, {SOCK_OBJECT, "OBJECT", 0, "Object", ""}, @@ -95,6 +96,7 @@ static const EnumPropertyItem node_socket_type_items[] = { {SOCK_INT, "INT", 0, "Integer", ""}, {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""}, {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, + {SOCK_ROTATION, "ROTATION", 0, "Rotation", ""}, {SOCK_STRING, "STRING", 0, "String", ""}, {SOCK_RGBA, "RGBA", 0, "RGBA", ""}, {SOCK_SHADER, "SHADER", 0, "Shader", ""}, @@ -510,6 +512,12 @@ static const EnumPropertyItem rna_node_combsep_color_items[] = { {0, NULL, 0, NULL, NULL}, }; +static const EnumPropertyItem rna_node_combine_separate_rotation_items[] = { + {NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ, "EULER_XYZ", ICON_NONE, "Euler", ""}, + {NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE, "AXIS_ANGLE", ICON_NONE, "Axis Angle", ""}, + {0, NULL, 0, NULL, NULL}, +}; + #ifndef RNA_RUNTIME static const EnumPropertyItem node_sampler_type_items[] = { {0, "NEAREST", 0, "Nearest", ""}, @@ -2084,6 +2092,7 @@ static bool switch_type_supported(const EnumPropertyItem *item) SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, + SOCK_ROTATION, SOCK_VECTOR, SOCK_STRING, SOCK_RGBA, @@ -2232,7 +2241,8 @@ static bool generic_attribute_type_supported(const EnumPropertyItem *item) CD_PROP_COLOR, CD_PROP_BOOL, CD_PROP_INT32, - CD_PROP_BYTE_COLOR); + CD_PROP_BYTE_COLOR, + CD_PROP_QUATERNION); } static const EnumPropertyItem *rna_GeometryNodeAttributeType_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), @@ -5339,6 +5349,28 @@ static void def_fn_combsep_color(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_fn_combine_rotation(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, rna_node_combine_separate_rotation_items); + RNA_def_property_ui_text(prop, "Mode", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + +static void def_fn_separate_rotation(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, rna_node_combine_separate_rotation_items); + RNA_def_property_ui_text(prop, "Mode", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + /* -- Shader Nodes ---------------------------------------------------------- */ static void def_sh_output(StructRNA *srna) @@ -11896,6 +11928,44 @@ static void rna_def_node_socket_bool(BlenderRNA *brna, RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL); } +static void rna_def_node_socket_rotation(BlenderRNA *brna, + const char *identifier, + const char *interface_idname) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); + RNA_def_struct_ui_text(srna, "Rotation Node Socket", "Rotation value socket of a node"); + RNA_def_struct_sdna(srna, "bNodeSocket"); + + RNA_def_struct_sdna_from(srna, "bNodeSocketValueRotation", "default_value"); + + prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_EULER); + RNA_def_property_float_sdna(prop, NULL, "value_euler"); + // RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); + + RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL); + + /* socket interface */ + srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); + RNA_def_struct_ui_text( + srna, "Rotation Node Socket Interface", "Rotation value socket of a node"); + RNA_def_struct_sdna(srna, "bNodeSocket"); + + RNA_def_struct_sdna_from(srna, "bNodeSocketValueRotation", "default_value"); + + prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_EULER); + RNA_def_property_float_sdna(prop, NULL, "value_euler"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); + + RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL); +} + static void rna_def_node_socket_vector(BlenderRNA *brna, const char *identifier, const char *interface_idname, @@ -12386,6 +12456,7 @@ static void rna_def_node_socket_standard_types(BlenderRNA *brna) brna, "NodeSocketIntFactor", "NodeSocketInterfaceIntFactor", PROP_FACTOR); rna_def_node_socket_bool(brna, "NodeSocketBool", "NodeSocketInterfaceBool"); + rna_def_node_socket_rotation(brna, "NodeSocketRotation", "NodeSocketInterfaceRotation"); rna_def_node_socket_vector(brna, "NodeSocketVector", "NodeSocketInterfaceVector", PROP_NONE); rna_def_node_socket_vector(brna, diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index d7d3cec3aaf..e54efcf92d9 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -4,6 +4,8 @@ #pragma once +#include "BLI_math_quaternion_types.hh" + #include "FN_field.hh" #include "FN_lazy_function.hh" #include "FN_multi_function_builder.hh" @@ -72,7 +74,7 @@ class GeoNodeExecParams { template static inline constexpr bool is_field_base_type_v = - is_same_any_v; + is_same_any_v; /** * Get the input value for the input socket with the given identifier. diff --git a/source/blender/nodes/NOD_socket_declarations.hh b/source/blender/nodes/NOD_socket_declarations.hh index a5d3a073bb1..dc08cd0c412 100644 --- a/source/blender/nodes/NOD_socket_declarations.hh +++ b/source/blender/nodes/NOD_socket_declarations.hh @@ -9,6 +9,7 @@ #include "RNA_types.h" #include "BLI_color.hh" +#include "BLI_math_euler_types.hh" #include "BLI_math_vector_types.hh" namespace blender::nodes::decl { @@ -136,6 +137,27 @@ class ColorBuilder : public SocketDeclarationBuilder { ColorBuilder &default_value(const ColorGeometry4f value); }; +class RotationBuilder; + +class Rotation : public SocketDeclaration { + public: + math::EulerXYZ default_value; + + friend RotationBuilder; + + using Builder = RotationBuilder; + + 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 RotationBuilder : public SocketDeclarationBuilder { + public: + RotationBuilder &default_value(const math::EulerXYZ &value); +}; + class StringBuilder; class String : public SocketDeclaration { @@ -387,6 +409,18 @@ inline StringBuilder &StringBuilder::default_value(std::string value) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name #RotationBuilder Inline Methods + * \{ */ + +inline RotationBuilder &RotationBuilder::default_value(const math::EulerXYZ &value) +{ + decl_->default_value = value; + return *this; +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name #IDSocketDeclaration and Children Inline Methods * \{ */ diff --git a/source/blender/nodes/geometry/node_geometry_tree.cc b/source/blender/nodes/geometry/node_geometry_tree.cc index d1a72bc8486..aeeef3f2105 100644 --- a/source/blender/nodes/geometry/node_geometry_tree.cc +++ b/source/blender/nodes/geometry/node_geometry_tree.cc @@ -98,6 +98,7 @@ static bool geometry_node_tree_socket_type_valid(bNodeTreeType * /*treetype*/, SOCK_VECTOR, SOCK_RGBA, SOCK_BOOLEAN, + SOCK_ROTATION, SOCK_INT, SOCK_STRING, SOCK_OBJECT, diff --git a/source/blender/nodes/intern/node_common.cc b/source/blender/nodes/intern/node_common.cc index a2013dc29a7..41592a71ba4 100644 --- a/source/blender/nodes/intern/node_common.cc +++ b/source/blender/nodes/intern/node_common.cc @@ -13,6 +13,7 @@ #include "BLI_listbase.h" #include "BLI_map.hh" +#include "BLI_math_euler.hh" #include "BLI_multi_value_map.hh" #include "BLI_set.hh" #include "BLI_stack.hh" @@ -207,6 +208,13 @@ static SocketDeclarationPtr declaration_for_interface_socket(const bNodeTree &nt dst = std::move(decl); break; } + case SOCK_ROTATION: { + const auto &value = *io_socket.default_value_typed(); + std::unique_ptr decl = std::make_unique(); + decl->default_value = math::EulerXYZ(float3(value.value_euler)); + dst = std::move(decl); + break; + } case SOCK_INT: { const auto &value = *io_socket.default_value_typed(); std::unique_ptr decl = std::make_unique(); diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index df7c897afa6..599b7d8375c 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -12,6 +12,8 @@ #include "BLI_color.hh" #include "BLI_listbase.h" +#include "BLI_math_euler.hh" +#include "BLI_math_quaternion_types.hh" #include "BLI_math_vector.h" #include "BLI_math_vector_types.hh" #include "BLI_string.h" @@ -341,6 +343,11 @@ void node_socket_init_default_value(bNodeSocket *sock) sock->default_value = dval; break; } + case SOCK_ROTATION: { + bNodeSocketValueRotation *dval = MEM_cnew(__func__); + sock->default_value = dval; + break; + } case SOCK_VECTOR: { static float default_value[] = {0.0f, 0.0f, 0.0f}; bNodeSocketValueVector *dval = MEM_cnew("node socket value vector"); @@ -458,6 +465,12 @@ void node_socket_copy_default_value(bNodeSocket *to, const bNodeSocket *from) *toval = *fromval; break; } + case SOCK_ROTATION: { + bNodeSocketValueRotation *toval = (bNodeSocketValueRotation *)to->default_value; + bNodeSocketValueRotation *fromval = (bNodeSocketValueRotation *)from->default_value; + *toval = *fromval; + break; + } case SOCK_STRING: { bNodeSocketValueString *toval = (bNodeSocketValueString *)to->default_value; bNodeSocketValueString *fromval = (bNodeSocketValueString *)from->default_value; @@ -625,6 +638,24 @@ static bNodeSocketType *make_socket_type_bool() return socktype; } +static bNodeSocketType *make_socket_type_rotation() +{ + bNodeSocketType *socktype = make_standard_socket_type(SOCK_ROTATION, PROP_NONE); + socktype->base_cpp_type = &blender::CPPType::get(); + socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) { + const auto &value = *socket.default_value_typed(); + const math::EulerXYZ euler(float3(value.value_euler)); + *static_cast(r_value) = math::to_quaternion(euler); + }; + socktype->geometry_nodes_cpp_type = &blender::CPPType::get>(); + socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) { + math::Quaternion value; + socket.typeinfo->get_base_cpp_value(socket, &value); + new (r_value) ValueOrField(value); + }; + return socktype; +} + static bNodeSocketType *make_socket_type_float(PropertySubType subtype) { bNodeSocketType *socktype = make_standard_socket_type(SOCK_FLOAT, subtype); @@ -798,6 +829,7 @@ void register_standard_node_socket_types() nodeRegisterSocketType(make_socket_type_int(PROP_FACTOR)); nodeRegisterSocketType(make_socket_type_bool()); + nodeRegisterSocketType(make_socket_type_rotation()); nodeRegisterSocketType(make_socket_type_vector(PROP_NONE)); nodeRegisterSocketType(make_socket_type_vector(PROP_TRANSLATION)); diff --git a/source/blender/nodes/intern/node_socket_declarations.cc b/source/blender/nodes/intern/node_socket_declarations.cc index 22772a0243e..357d431ddc8 100644 --- a/source/blender/nodes/intern/node_socket_declarations.cc +++ b/source/blender/nodes/intern/node_socket_declarations.cc @@ -381,6 +381,61 @@ bNodeSocket &Color::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket & return socket; } +/** \} */ +/* -------------------------------------------------------------------- */ +/** \name #Rotation + * \{ */ + +bNodeSocket &Rotation::build(bNodeTree &ntree, bNode &node) const +{ + bNodeSocket &socket = *nodeAddStaticSocket(&ntree, + &node, + this->in_out, + SOCK_ROTATION, + PROP_NONE, + this->identifier.c_str(), + this->name.c_str()); + this->set_common_flags(socket); + bNodeSocketValueRotation &value = *static_cast(socket.default_value); + copy_v3_v3(value.value_euler, float3(this->default_value)); + return socket; +} + +bool Rotation::matches(const bNodeSocket &socket) const +{ + if (!this->matches_common_data(socket)) { + if (socket.name != this->name) { + return false; + } + if (socket.identifier != this->identifier) { + return false; + } + } + if (socket.type != SOCK_ROTATION) { + return false; + } + return true; +} + +bool Rotation::can_connect(const bNodeSocket &socket) const +{ + if (!sockets_can_connect(*this, socket)) { + return false; + } + return socket.type == SOCK_ROTATION; +} + +bNodeSocket &Rotation::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const +{ + if (socket.type != SOCK_ROTATION) { + BLI_assert(socket.in_out == this->in_out); + return this->build(ntree, node); + } + this->set_common_flags(socket); + STRNCPY(socket.name, this->name.c_str()); + return socket; +} + /** \} */ /* -------------------------------------------------------------------- */ -- 2.30.2 From e3c2f57099b5f59423dda999ca8b87d263efd182 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 15 May 2023 17:12:25 -0400 Subject: [PATCH 2/4] Geometry Nodes: Add separate and combine rotation nodes --- .../startup/bl_ui/node_add_menu_geometry.py | 2 + source/blender/blenkernel/BKE_node.h | 2 + source/blender/nodes/NOD_static_types.h | 2 + source/blender/nodes/function/CMakeLists.txt | 2 + .../nodes/function/node_function_register.cc | 2 + .../nodes/function/node_function_register.hh | 2 + .../nodes/node_fn_combine_rotation.cc | 96 ++++++++++++++ .../nodes/node_fn_separate_rotation.cc | 118 ++++++++++++++++++ 8 files changed, 226 insertions(+) create mode 100644 source/blender/nodes/function/nodes/node_fn_combine_rotation.cc create mode 100644 source/blender/nodes/function/nodes/node_fn_separate_rotation.cc diff --git a/scripts/startup/bl_ui/node_add_menu_geometry.py b/scripts/startup/bl_ui/node_add_menu_geometry.py index ea7c40f1178..03dad66fba8 100644 --- a/scripts/startup/bl_ui/node_add_menu_geometry.py +++ b/scripts/startup/bl_ui/node_add_menu_geometry.py @@ -550,7 +550,9 @@ class NODE_MT_category_GEO_UTILITIES_ROTATION(Menu): def draw(self, _context): layout = self.layout node_add_menu.add_node_type(layout, "FunctionNodeAlignEulerToVector") + node_add_menu.add_node_type(layout, "FunctionNodeCombineRotation") node_add_menu.add_node_type(layout, "FunctionNodeRotateEuler") + node_add_menu.add_node_type(layout, "FunctionNodeSeparateRotation") node_add_menu.draw_assets_for_catalog(layout, self.bl_label) diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 98adde6711b..ae8e45b8d12 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1337,6 +1337,8 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i #define FN_NODE_INPUT_INT 1220 #define FN_NODE_SEPARATE_COLOR 1221 #define FN_NODE_COMBINE_COLOR 1222 +#define FN_NODE_COMBINE_ROTATION 1223 +#define FN_NODE_SEPARATE_ROTATION 1224 /** \} */ diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 1bca649a7bf..9bba365cbea 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -266,6 +266,7 @@ DefNode(TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DI DefNode(FunctionNode, FN_NODE_ALIGN_EULER_TO_VECTOR, def_fn_align_euler_to_vector, "ALIGN_EULER_TO_VECTOR", AlignEulerToVector, "Align Euler to Vector", "") DefNode(FunctionNode, FN_NODE_BOOLEAN_MATH, def_boolean_math, "BOOLEAN_MATH", BooleanMath, "Boolean Math", "") DefNode(FunctionNode, FN_NODE_COMBINE_COLOR, def_fn_combsep_color, "COMBINE_COLOR", CombineColor, "Combine Color", "") +DefNode(FunctionNode, FN_NODE_COMBINE_ROTATION, def_fn_combine_rotation, "COMBINE_ROTATION", CombineRotation, "Combine Rotation", "") DefNode(FunctionNode, FN_NODE_COMPARE, def_compare, "COMPARE", Compare, "Compare", "") DefNode(FunctionNode, FN_NODE_FLOAT_TO_INT, def_float_to_int, "FLOAT_TO_INT", FloatToInt, "Float to Integer", "") DefNode(FunctionNode, FN_NODE_INPUT_BOOL, def_fn_input_bool, "INPUT_BOOL", InputBool, "Boolean", "") @@ -278,6 +279,7 @@ DefNode(FunctionNode, FN_NODE_RANDOM_VALUE, def_fn_random_value, "RANDOM_VALUE", DefNode(FunctionNode, FN_NODE_REPLACE_STRING, 0, "REPLACE_STRING", ReplaceString, "Replace String", "") DefNode(FunctionNode, FN_NODE_ROTATE_EULER, def_fn_rotate_euler, "ROTATE_EULER", RotateEuler, "Rotate Euler", "") DefNode(FunctionNode, FN_NODE_SEPARATE_COLOR, def_fn_combsep_color, "SEPARATE_COLOR", SeparateColor, "Separate Color", "") +DefNode(FunctionNode, FN_NODE_SEPARATE_ROTATION, def_fn_separate_rotation, "SEPARATE_ROTATION", SeparateRotation, "Separate Rotation", "") 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_VALUE_TO_STRING, 0, "VALUE_TO_STRING", ValueToString, "Value to String", "") diff --git a/source/blender/nodes/function/CMakeLists.txt b/source/blender/nodes/function/CMakeLists.txt index b1d86497339..cf10c9250b0 100644 --- a/source/blender/nodes/function/CMakeLists.txt +++ b/source/blender/nodes/function/CMakeLists.txt @@ -24,6 +24,7 @@ set(SRC nodes/node_fn_align_euler_to_vector.cc nodes/node_fn_boolean_math.cc nodes/node_fn_combine_color.cc + nodes/node_fn_combine_rotation.cc nodes/node_fn_compare.cc nodes/node_fn_float_to_int.cc nodes/node_fn_input_bool.cc @@ -36,6 +37,7 @@ set(SRC nodes/node_fn_replace_string.cc nodes/node_fn_rotate_euler.cc nodes/node_fn_separate_color.cc + nodes/node_fn_separate_rotation.cc nodes/node_fn_slice_string.cc nodes/node_fn_string_length.cc nodes/node_fn_value_to_string.cc diff --git a/source/blender/nodes/function/node_function_register.cc b/source/blender/nodes/function/node_function_register.cc index 4eb8809da7c..bfb0b7d6511 100644 --- a/source/blender/nodes/function/node_function_register.cc +++ b/source/blender/nodes/function/node_function_register.cc @@ -11,6 +11,7 @@ void register_function_nodes() register_node_type_fn_align_euler_to_vector(); register_node_type_fn_boolean_math(); register_node_type_fn_combine_color(); + register_node_type_fn_combine_rotation(); register_node_type_fn_compare(); register_node_type_fn_float_to_int(); register_node_type_fn_input_bool(); @@ -23,6 +24,7 @@ void register_function_nodes() register_node_type_fn_replace_string(); register_node_type_fn_rotate_euler(); register_node_type_fn_separate_color(); + register_node_type_fn_separate_rotation(); register_node_type_fn_slice_string(); register_node_type_fn_string_length(); register_node_type_fn_value_to_string(); diff --git a/source/blender/nodes/function/node_function_register.hh b/source/blender/nodes/function/node_function_register.hh index cfd8a5f64c6..933c09a2d35 100644 --- a/source/blender/nodes/function/node_function_register.hh +++ b/source/blender/nodes/function/node_function_register.hh @@ -7,6 +7,7 @@ void register_node_type_fn_align_euler_to_vector(); void register_node_type_fn_boolean_math(); void register_node_type_fn_combine_color(); +void register_node_type_fn_combine_rotation(); void register_node_type_fn_compare(); void register_node_type_fn_float_to_int(); void register_node_type_fn_input_bool(); @@ -19,6 +20,7 @@ void register_node_type_fn_random_value(); void register_node_type_fn_replace_string(); void register_node_type_fn_rotate_euler(); void register_node_type_fn_separate_color(); +void register_node_type_fn_separate_rotation(); void register_node_type_fn_slice_string(); void register_node_type_fn_string_length(); void register_node_type_fn_value_to_string(); diff --git a/source/blender/nodes/function/nodes/node_fn_combine_rotation.cc b/source/blender/nodes/function/nodes/node_fn_combine_rotation.cc new file mode 100644 index 00000000000..807bb70de76 --- /dev/null +++ b/source/blender/nodes/function/nodes/node_fn_combine_rotation.cc @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_math_axis_angle.hh" +#include "BLI_math_euler.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "node_function_util.hh" + +namespace blender::nodes::node_fn_combine_rotation_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.is_function_node(); + b.add_input(N_("Euler")).subtype(PROP_EULER).make_available([](bNode &node) { + node.custom1 = NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ; + }); + b.add_input(N_("Axis")) + .default_value({0.0f, 0.0f, 1.0f}) + .make_available( + [](bNode &node) { node.custom1 = NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE; }); + b.add_input(N_("Angle")).subtype(PROP_ANGLE).make_available([](bNode &node) { + node.custom1 = NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE; + }); + b.add_output(N_("Rotation")); +}; + +static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) +{ + uiItemR(layout, ptr, "mode", 0, "", ICON_NONE); +} + +static void node_init(bNodeTree * /*tree*/, bNode *node) +{ + node->custom1 = NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ; +} + +static void node_update(bNodeTree *tree, bNode *node) +{ + bke::nodeSetSocketAvailability(tree, + static_cast(BLI_findlink(&node->inputs, 0)), + node->custom1 == NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ); + bke::nodeSetSocketAvailability(tree, + static_cast(BLI_findlink(&node->inputs, 1)), + node->custom1 == NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE); + bke::nodeSetSocketAvailability(tree, + static_cast(BLI_findlink(&node->inputs, 2)), + node->custom1 == NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE); +} + +static const mf::MultiFunction *get_multi_function(const bNode &bnode) +{ + const auto mode = NodeCombineSeparateRotatioNMode(bnode.custom1); + + static auto euler_xyz_fn = mf::build::SI1_SO( + "Euler XYZ to Quaternion", + [](float3 euler) { return math::to_quaternion(math::EulerXYZ(euler)); }); + static auto axis_angle_fn = mf::build::SI2_SO( + "Axis Angle to Quaternion", [](float3 axis, float angle) { + return math::normalize(math::to_quaternion(math::AxisAngle(math::normalize(axis), angle))); + }); + + switch (mode) { + case NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ: + return &euler_xyz_fn; + case NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE: + return &axis_angle_fn; + } + BLI_assert_unreachable(); + return nullptr; +} + +static void node_build_multi_function(NodeMultiFunctionBuilder &builder) +{ + const mf::MultiFunction *fn = get_multi_function(builder.node()); + builder.set_matching_fn(fn); +} + +} // namespace blender::nodes::node_fn_combine_rotation_cc + +void register_node_type_fn_combine_rotation(void) +{ + namespace file_ns = blender::nodes::node_fn_combine_rotation_cc; + + static bNodeType ntype; + + fn_node_type_base(&ntype, FN_NODE_COMBINE_ROTATION, "Combine Rotation", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::node_declare; + ntype.initfunc = file_ns::node_init; + ntype.updatefunc = file_ns::node_update; + ntype.build_multi_function = file_ns::node_build_multi_function; + ntype.draw_buttons = file_ns::node_layout; + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/function/nodes/node_fn_separate_rotation.cc b/source/blender/nodes/function/nodes/node_fn_separate_rotation.cc new file mode 100644 index 00000000000..ed0b58a3eed --- /dev/null +++ b/source/blender/nodes/function/nodes/node_fn_separate_rotation.cc @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_math_axis_angle.hh" +#include "BLI_math_euler.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "node_function_util.hh" + +namespace blender::nodes::node_fn_separate_rotation_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.is_function_node(); + b.add_input(N_("Rotation")); + b.add_output(N_("Euler")).subtype(PROP_EULER).make_available([](bNode &node) { + node.custom1 = NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ; + }); + b.add_output(N_("Axis")).make_available([](bNode &node) { + node.custom1 = NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE; + }); + b.add_output(N_("Angle")).subtype(PROP_ANGLE).make_available([](bNode &node) { + node.custom1 = NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE; + }); +}; + +static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) +{ + uiItemR(layout, ptr, "mode", 0, "", ICON_NONE); +} + +static void node_init(bNodeTree * /*tree*/, bNode *node) +{ + node->custom1 = NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ; +} + +static void node_update(bNodeTree *tree, bNode *node) +{ + bke::nodeSetSocketAvailability(tree, + static_cast(BLI_findlink(&node->outputs, 0)), + node->custom1 == NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ); + bke::nodeSetSocketAvailability(tree, + static_cast(BLI_findlink(&node->outputs, 1)), + node->custom1 == NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE); + bke::nodeSetSocketAvailability(tree, + static_cast(BLI_findlink(&node->outputs, 2)), + node->custom1 == NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE); +} + +class QuaterniontoAxisAngleFunction : public mf::MultiFunction { + public: + QuaterniontoAxisAngleFunction() + { + static mf::Signature signature_; + mf::SignatureBuilder builder{"Quaternion to Axis Angle", signature_}; + builder.single_input("Quaternion"); + builder.single_output("Axis"); + builder.single_output("Angle"); + this->set_signature(&signature_); + } + + void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override + { + const VArraySpan quaternions = + params.readonly_single_input(0, "Quaternion"); + MutableSpan axes = params.uninitialized_single_output(2, "Axis"); + MutableSpan angles = params.uninitialized_single_output(3, "Angle"); + mask.foreach_index([&](const int64_t i) { + const math::AxisAngle axis_angle = math::to_axis_angle(quaternions[i]); + axes[i] = axis_angle.axis(); + angles[i] = axis_angle.angle().radian(); + }); + } +}; + +static const mf::MultiFunction *get_multi_function(const bNode &bnode) +{ + const auto mode = NodeCombineSeparateRotatioNMode(bnode.custom1); + + static auto euler_xyz_fn = mf::build::SI1_SO( + "Quaternion to Euler XYZ", + [](const math::Quaternion quaternion) { return math::to_euler(quaternion); }); + static QuaterniontoAxisAngleFunction axis_angle_fn; + + switch (mode) { + case NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ: + return &euler_xyz_fn; + case NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE: + return &axis_angle_fn; + } + BLI_assert_unreachable(); + return nullptr; +} + +static void node_build_multi_function(NodeMultiFunctionBuilder &builder) +{ + const mf::MultiFunction *fn = get_multi_function(builder.node()); + builder.set_matching_fn(fn); +} + +} // namespace blender::nodes::node_fn_separate_rotation_cc + +void register_node_type_fn_separate_rotation(void) +{ + namespace file_ns = blender::nodes::node_fn_separate_rotation_cc; + + static bNodeType ntype; + + fn_node_type_base(&ntype, FN_NODE_SEPARATE_ROTATION, "Separate Rotation", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::node_declare; + ntype.initfunc = file_ns::node_init; + ntype.updatefunc = file_ns::node_update; + ntype.build_multi_function = file_ns::node_build_multi_function; + ntype.draw_buttons = file_ns::node_layout; + + nodeRegisterType(&ntype); +} -- 2.30.2 From 07fc1aadafaa13fb6087aba5001cb19fd6ee5629 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 15 May 2023 17:16:13 -0400 Subject: [PATCH 3/4] Geometry Nodes: Support rotation sockets in many multi-type nodes --- .../nodes/geometry/node_geometry_util.cc | 2 + .../nodes/node_geo_attribute_capture.cc | 11 +++++ .../geometry/nodes/node_geo_blur_attribute.cc | 4 ++ .../geometry/nodes/node_geo_curve_sample.cc | 28 ++++++++--- .../nodes/node_geo_evaluate_at_index.cc | 6 +++ .../nodes/node_geo_evaluate_on_domain.cc | 8 +++ .../nodes/node_geo_input_named_attribute.cc | 6 +++ .../nodes/geometry/nodes/node_geo_raycast.cc | 6 +++ .../geometry/nodes/node_geo_sample_index.cc | 16 ++++-- .../nodes/node_geo_sample_nearest_surface.cc | 12 +++++ .../nodes/node_geo_sample_uv_surface.cc | 12 +++++ .../nodes/node_geo_simulation_output.cc | 9 ++++ .../nodes/node_geo_store_named_attribute.cc | 6 +++ .../nodes/geometry/nodes/node_geo_switch.cc | 49 ++++++++++++------- .../nodes/geometry/nodes/node_geo_viewer.cc | 13 ++++- .../nodes/intern/geometry_nodes_execute.cc | 12 +++++ 16 files changed, 168 insertions(+), 32 deletions(-) diff --git a/source/blender/nodes/geometry/node_geometry_util.cc b/source/blender/nodes/geometry/node_geometry_util.cc index c67ed92a09e..72c3f0c4bde 100644 --- a/source/blender/nodes/geometry/node_geometry_util.cc +++ b/source/blender/nodes/geometry/node_geometry_util.cc @@ -28,6 +28,8 @@ std::optional node_data_type_to_custom_data_type(const eNodeSoc return CD_PROP_COLOR; case SOCK_BOOLEAN: return CD_PROP_BOOL; + case SOCK_ROTATION: + return CD_PROP_QUATERNION; case SOCK_INT: return CD_PROP_INT32; case SOCK_STRING: diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc index 7ba55a88cf8..a39af7fa8e7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc @@ -23,6 +23,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input("Value", "Value_002").field_on_all(); b.add_input("Value", "Value_003").field_on_all(); b.add_input("Value", "Value_004").field_on_all(); + b.add_input("Value", "Value_005").field_on_all(); b.add_output("Geometry").propagate_all(); b.add_output("Attribute").field_on_all(); @@ -30,6 +31,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_output("Attribute", "Attribute_002").field_on_all(); b.add_output("Attribute", "Attribute_003").field_on_all(); b.add_output("Attribute", "Attribute_004").field_on_all(); + b.add_output("Attribute", "Attribute_005").field_on_all(); } static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) @@ -60,12 +62,14 @@ static void node_update(bNodeTree *ntree, bNode *node) bNodeSocket *socket_value_color4f = socket_value_float->next; bNodeSocket *socket_value_boolean = socket_value_color4f->next; bNodeSocket *socket_value_int32 = socket_value_boolean->next; + bNodeSocket *socket_value_quat = socket_value_int32->next; bke::nodeSetSocketAvailability(ntree, socket_value_vector, data_type == CD_PROP_FLOAT3); bke::nodeSetSocketAvailability(ntree, socket_value_float, data_type == CD_PROP_FLOAT); bke::nodeSetSocketAvailability(ntree, socket_value_color4f, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, socket_value_boolean, data_type == CD_PROP_BOOL); bke::nodeSetSocketAvailability(ntree, socket_value_int32, data_type == CD_PROP_INT32); + bke::nodeSetSocketAvailability(ntree, socket_value_quat, data_type == CD_PROP_QUATERNION); bNodeSocket *out_socket_value_geometry = static_cast(node->outputs.first); bNodeSocket *out_socket_value_vector = out_socket_value_geometry->next; @@ -73,12 +77,14 @@ static void node_update(bNodeTree *ntree, bNode *node) bNodeSocket *out_socket_value_color4f = out_socket_value_float->next; bNodeSocket *out_socket_value_boolean = out_socket_value_color4f->next; bNodeSocket *out_socket_value_int32 = out_socket_value_boolean->next; + bNodeSocket *out_socket_value_quat = out_socket_value_int32->next; bke::nodeSetSocketAvailability(ntree, out_socket_value_vector, data_type == CD_PROP_FLOAT3); bke::nodeSetSocketAvailability(ntree, out_socket_value_float, data_type == CD_PROP_FLOAT); bke::nodeSetSocketAvailability(ntree, out_socket_value_color4f, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, out_socket_value_boolean, data_type == CD_PROP_BOOL); bke::nodeSetSocketAvailability(ntree, out_socket_value_int32, data_type == CD_PROP_INT32); + bke::nodeSetSocketAvailability(ntree, out_socket_value_quat, data_type == CD_PROP_QUATERNION); } static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) @@ -115,6 +121,8 @@ static StringRefNull identifier_suffix(eCustomDataType data_type) return "_001"; case CD_PROP_INT32: return "_004"; + case CD_PROP_QUATERNION: + return "_005"; case CD_PROP_COLOR: return "_002"; case CD_PROP_BOOL: @@ -172,6 +180,9 @@ static void node_geo_exec(GeoNodeExecParams params) case CD_PROP_INT32: field = params.get_input>(input_identifier); break; + case CD_PROP_QUATERNION: + field = params.get_input>(input_identifier); + break; default: break; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_blur_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_blur_attribute.cc index e43e46bd458..42a34cb4acd 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_blur_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_blur_attribute.cc @@ -97,6 +97,10 @@ static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) if (fixed_data_type == CD_PROP_STRING) { return; } + if (fixed_data_type == CD_PROP_QUATERNION) { + /* Don't implement quaternion 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; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc index 4dd6603da88..c99601f2547 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc @@ -28,6 +28,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input("Value", "Value_Vector").hide_value().field_on_all(); b.add_input("Value", "Value_Color").hide_value().field_on_all(); b.add_input("Value", "Value_Bool").hide_value().field_on_all(); + b.add_input("Value", "Value_Rotation").hide_value().field_on_all(); b.add_input("Factor") .min(0.0f) @@ -44,15 +45,16 @@ static void node_declare(NodeDeclarationBuilder &b) node_storage(node).use_all_curves = false; }); - b.add_output("Value", "Value_Float").dependent_field({6, 7, 8}); - b.add_output("Value", "Value_Int").dependent_field({6, 7, 8}); - b.add_output("Value", "Value_Vector").dependent_field({6, 7, 8}); - b.add_output("Value", "Value_Color").dependent_field({6, 7, 8}); - b.add_output("Value", "Value_Bool").dependent_field({6, 7, 8}); + b.add_output("Value", "Value_Float").dependent_field({7, 8, 9}); + b.add_output("Value", "Value_Int").dependent_field({7, 8, 9}); + b.add_output("Value", "Value_Vector").dependent_field({7, 8, 9}); + b.add_output("Value", "Value_Color").dependent_field({7, 8, 9}); + b.add_output("Value", "Value_Bool").dependent_field({7, 8, 9}); + b.add_output("Value", "Value_Rotation").dependent_field({7, 8, 9}); - b.add_output("Position").dependent_field({6, 7, 8}); - b.add_output("Tangent").dependent_field({6, 7, 8}); - b.add_output("Normal").dependent_field({6, 7, 8}); + b.add_output("Position").dependent_field({7, 8, 9}); + b.add_output("Tangent").dependent_field({7, 8, 9}); + b.add_output("Normal").dependent_field({7, 8, 9}); } static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) @@ -82,6 +84,7 @@ static void node_update(bNodeTree *ntree, bNode *node) bNodeSocket *in_socket_vector = in_socket_int32->next; bNodeSocket *in_socket_color4f = in_socket_vector->next; bNodeSocket *in_socket_bool = in_socket_color4f->next; + bNodeSocket *in_socket_quat = in_socket_bool->next; bNodeSocket *factor = in_socket_bool->next; bNodeSocket *length = factor->next; @@ -96,18 +99,21 @@ static void node_update(bNodeTree *ntree, bNode *node) bke::nodeSetSocketAvailability(ntree, in_socket_color4f, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, in_socket_bool, data_type == CD_PROP_BOOL); bke::nodeSetSocketAvailability(ntree, in_socket_int32, data_type == CD_PROP_INT32); + bke::nodeSetSocketAvailability(ntree, in_socket_quat, data_type == CD_PROP_QUATERNION); bNodeSocket *out_socket_float = static_cast(node->outputs.first); bNodeSocket *out_socket_int32 = out_socket_float->next; bNodeSocket *out_socket_vector = out_socket_int32->next; bNodeSocket *out_socket_color4f = out_socket_vector->next; bNodeSocket *out_socket_bool = out_socket_color4f->next; + bNodeSocket *out_socket_quat = out_socket_bool->next; bke::nodeSetSocketAvailability(ntree, out_socket_vector, data_type == CD_PROP_FLOAT3); bke::nodeSetSocketAvailability(ntree, out_socket_float, data_type == CD_PROP_FLOAT); bke::nodeSetSocketAvailability(ntree, out_socket_color4f, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, out_socket_bool, data_type == CD_PROP_BOOL); bke::nodeSetSocketAvailability(ntree, out_socket_int32, data_type == CD_PROP_INT32); + bke::nodeSetSocketAvailability(ntree, out_socket_quat, data_type == CD_PROP_QUATERNION); } static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) @@ -464,6 +470,8 @@ static GField get_input_attribute_field(GeoNodeExecParams ¶ms, const eCustom return params.extract_input>("Value_Bool"); case CD_PROP_INT32: return params.extract_input>("Value_Int"); + case CD_PROP_QUATERNION: + return params.extract_input>("Value_Rotation"); default: BLI_assert_unreachable(); } @@ -493,6 +501,10 @@ static void output_attribute_field(GeoNodeExecParams ¶ms, GField field) params.set_output("Value_Int", Field(field)); break; } + case CD_PROP_QUATERNION: { + params.set_output("Value_Rotation", Field(field)); + break; + } default: break; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_evaluate_at_index.cc b/source/blender/nodes/geometry/nodes/node_geo_evaluate_at_index.cc index aaeb2b52b66..621709f25dc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_evaluate_at_index.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_evaluate_at_index.cc @@ -93,24 +93,28 @@ static void node_update(bNodeTree *ntree, bNode *node) bNodeSocket *sock_in_vector = sock_in_int->next; bNodeSocket *sock_in_color = sock_in_vector->next; bNodeSocket *sock_in_bool = sock_in_color->next; + bNodeSocket *sock_in_quat = sock_in_bool->next; bNodeSocket *sock_out_float = static_cast(node->outputs.first); bNodeSocket *sock_out_int = sock_out_float->next; bNodeSocket *sock_out_vector = sock_out_int->next; bNodeSocket *sock_out_color = sock_out_vector->next; bNodeSocket *sock_out_bool = sock_out_color->next; + bNodeSocket *sock_out_quat = sock_out_bool->next; bke::nodeSetSocketAvailability(ntree, sock_in_float, data_type == CD_PROP_FLOAT); bke::nodeSetSocketAvailability(ntree, sock_in_int, data_type == CD_PROP_INT32); bke::nodeSetSocketAvailability(ntree, sock_in_vector, data_type == CD_PROP_FLOAT3); bke::nodeSetSocketAvailability(ntree, sock_in_color, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, sock_in_bool, data_type == CD_PROP_BOOL); + bke::nodeSetSocketAvailability(ntree, sock_in_quat, data_type == CD_PROP_QUATERNION); bke::nodeSetSocketAvailability(ntree, sock_out_float, data_type == CD_PROP_FLOAT); bke::nodeSetSocketAvailability(ntree, sock_out_int, data_type == CD_PROP_INT32); bke::nodeSetSocketAvailability(ntree, sock_out_vector, data_type == CD_PROP_FLOAT3); bke::nodeSetSocketAvailability(ntree, sock_out_color, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, sock_out_bool, data_type == CD_PROP_BOOL); + bke::nodeSetSocketAvailability(ntree, sock_out_quat, data_type == CD_PROP_QUATERNION); } static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) @@ -148,6 +152,8 @@ static StringRefNull identifier_suffix(eCustomDataType data_type) return "Color"; case CD_PROP_FLOAT3: return "Vector"; + case CD_PROP_QUATERNION: + return "Rotation"; default: BLI_assert_unreachable(); return ""; diff --git a/source/blender/nodes/geometry/nodes/node_geo_evaluate_on_domain.cc b/source/blender/nodes/geometry/nodes/node_geo_evaluate_on_domain.cc index 8bcfe0c4537..73404d46b46 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_evaluate_on_domain.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_evaluate_on_domain.cc @@ -22,12 +22,14 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input("Value", "Value_Vector").supports_field(); b.add_input("Value", "Value_Color").supports_field(); b.add_input("Value", "Value_Bool").supports_field(); + b.add_input("Value", "Value_Rotation").supports_field(); b.add_output("Value", "Value_Float").field_source_reference_all(); b.add_output("Value", "Value_Int").field_source_reference_all(); b.add_output("Value", "Value_Vector").field_source_reference_all(); b.add_output("Value", "Value_Color").field_source_reference_all(); b.add_output("Value", "Value_Bool").field_source_reference_all(); + b.add_output("Value", "Value_Rotation").field_source_reference_all(); } static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) @@ -51,24 +53,28 @@ static void node_update(bNodeTree *ntree, bNode *node) bNodeSocket *sock_in_vector = sock_in_int->next; bNodeSocket *sock_in_color = sock_in_vector->next; bNodeSocket *sock_in_bool = sock_in_color->next; + bNodeSocket *sock_in_quat = sock_in_bool->next; bNodeSocket *sock_out_float = static_cast(node->outputs.first); bNodeSocket *sock_out_int = sock_out_float->next; bNodeSocket *sock_out_vector = sock_out_int->next; bNodeSocket *sock_out_color = sock_out_vector->next; bNodeSocket *sock_out_bool = sock_out_color->next; + bNodeSocket *sock_out_quat = sock_out_bool->next; bke::nodeSetSocketAvailability(ntree, sock_in_float, data_type == CD_PROP_FLOAT); bke::nodeSetSocketAvailability(ntree, sock_in_int, data_type == CD_PROP_INT32); bke::nodeSetSocketAvailability(ntree, sock_in_vector, data_type == CD_PROP_FLOAT3); bke::nodeSetSocketAvailability(ntree, sock_in_color, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, sock_in_bool, data_type == CD_PROP_BOOL); + bke::nodeSetSocketAvailability(ntree, sock_in_quat, data_type == CD_PROP_QUATERNION); bke::nodeSetSocketAvailability(ntree, sock_out_float, data_type == CD_PROP_FLOAT); bke::nodeSetSocketAvailability(ntree, sock_out_int, data_type == CD_PROP_INT32); bke::nodeSetSocketAvailability(ntree, sock_out_vector, data_type == CD_PROP_FLOAT3); bke::nodeSetSocketAvailability(ntree, sock_out_color, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, sock_out_bool, data_type == CD_PROP_BOOL); + bke::nodeSetSocketAvailability(ntree, sock_out_quat, data_type == CD_PROP_QUATERNION); } static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) @@ -139,6 +145,8 @@ static StringRefNull identifier_suffix(eCustomDataType data_type) return "Color"; case CD_PROP_FLOAT3: return "Vector"; + case CD_PROP_QUATERNION: + return "Rotation"; default: BLI_assert_unreachable(); return ""; diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc index 96b0d8ce63c..1aaa58e0a60 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc @@ -22,6 +22,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_output("Attribute", "Attribute_Color").field_source(); b.add_output("Attribute", "Attribute_Bool").field_source(); b.add_output("Attribute", "Attribute_Int").field_source(); + b.add_output("Attribute", "Attribute_Rotation").field_source(); b.add_output("Exists").field_source(); } @@ -48,12 +49,14 @@ static void node_update(bNodeTree *ntree, bNode *node) bNodeSocket *socket_color4f = socket_float->next; bNodeSocket *socket_boolean = socket_color4f->next; bNodeSocket *socket_int32 = socket_boolean->next; + bNodeSocket *socket_quat = socket_int32->next; bke::nodeSetSocketAvailability(ntree, socket_vector, data_type == CD_PROP_FLOAT3); bke::nodeSetSocketAvailability(ntree, socket_float, data_type == CD_PROP_FLOAT); bke::nodeSetSocketAvailability(ntree, socket_color4f, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, socket_boolean, data_type == CD_PROP_BOOL); bke::nodeSetSocketAvailability(ntree, socket_int32, data_type == CD_PROP_INT32); + bke::nodeSetSocketAvailability(ntree, socket_quat, data_type == CD_PROP_QUATERNION); } static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) @@ -145,6 +148,9 @@ static void node_geo_exec(GeoNodeExecParams params) case CD_PROP_INT32: params.set_output("Attribute_Int", AttributeFieldInput::Create(name)); break; + case CD_PROP_QUATERNION: + params.set_output("Attribute_Rotation", AttributeFieldInput::Create(name)); + break; default: break; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc index 7bc6464a0c8..d4dab76aae5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc @@ -32,6 +32,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input("Attribute", "Attribute_002").hide_value().field_on_all(); b.add_input("Attribute", "Attribute_003").hide_value().field_on_all(); b.add_input("Attribute", "Attribute_004").hide_value().field_on_all(); + b.add_input("Attribute", "Attribute_005").hide_value().field_on_all(); b.add_input("Source Position").implicit_field(implicit_field_inputs::position); b.add_input("Ray Direction").default_value({0.0f, 0.0f, -1.0f}).supports_field(); @@ -51,6 +52,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_output("Attribute", "Attribute_002").dependent_field({6, 7, 8}); b.add_output("Attribute", "Attribute_003").dependent_field({6, 7, 8}); b.add_output("Attribute", "Attribute_004").dependent_field({6, 7, 8}); + b.add_output("Attribute", "Attribute_005").dependent_field({6, 7, 8}); } static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) @@ -77,24 +79,28 @@ static void node_update(bNodeTree *ntree, bNode *node) bNodeSocket *socket_color4f = socket_float->next; bNodeSocket *socket_boolean = socket_color4f->next; bNodeSocket *socket_int32 = socket_boolean->next; + bNodeSocket *socket_quat = socket_boolean->next; bke::nodeSetSocketAvailability(ntree, socket_vector, data_type == CD_PROP_FLOAT3); bke::nodeSetSocketAvailability(ntree, socket_float, data_type == CD_PROP_FLOAT); bke::nodeSetSocketAvailability(ntree, socket_color4f, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, socket_boolean, data_type == CD_PROP_BOOL); bke::nodeSetSocketAvailability(ntree, socket_int32, data_type == CD_PROP_INT32); + bke::nodeSetSocketAvailability(ntree, socket_quat, data_type == CD_PROP_QUATERNION); bNodeSocket *out_socket_vector = static_cast(BLI_findlink(&node->outputs, 4)); bNodeSocket *out_socket_float = out_socket_vector->next; bNodeSocket *out_socket_color4f = out_socket_float->next; bNodeSocket *out_socket_boolean = out_socket_color4f->next; bNodeSocket *out_socket_int32 = out_socket_boolean->next; + bNodeSocket *out_socket_quat = out_socket_boolean->next; bke::nodeSetSocketAvailability(ntree, out_socket_vector, data_type == CD_PROP_FLOAT3); bke::nodeSetSocketAvailability(ntree, out_socket_float, data_type == CD_PROP_FLOAT); bke::nodeSetSocketAvailability(ntree, out_socket_color4f, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, out_socket_boolean, data_type == CD_PROP_BOOL); bke::nodeSetSocketAvailability(ntree, out_socket_int32, data_type == CD_PROP_INT32); + bke::nodeSetSocketAvailability(ntree, out_socket_quat, data_type == CD_PROP_QUATERNION); } static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_index.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_index.cc index 8f0eacd65db..6fce57fd1dc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sample_index.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_index.cc @@ -65,14 +65,16 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input("Value", "Value_Vector").hide_value().field_on_all(); b.add_input("Value", "Value_Color").hide_value().field_on_all(); b.add_input("Value", "Value_Bool").hide_value().field_on_all(); + b.add_input("Value", "Value_Rotation").hide_value().field_on_all(); b.add_input("Index").supports_field().description( "Which element to retrieve a value from on the geometry"); - b.add_output("Value", "Value_Float").dependent_field({6}); - b.add_output("Value", "Value_Int").dependent_field({6}); - b.add_output("Value", "Value_Vector").dependent_field({6}); - b.add_output("Value", "Value_Color").dependent_field({6}); - b.add_output("Value", "Value_Bool").dependent_field({6}); + b.add_output("Value", "Value_Float").dependent_field({7}); + b.add_output("Value", "Value_Int").dependent_field({7}); + b.add_output("Value", "Value_Vector").dependent_field({7}); + b.add_output("Value", "Value_Color").dependent_field({7}); + b.add_output("Value", "Value_Bool").dependent_field({7}); + b.add_output("Value", "Value_Rotation").dependent_field({7}); } static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) @@ -101,24 +103,28 @@ static void node_update(bNodeTree *ntree, bNode *node) bNodeSocket *in_socket_vector = in_socket_int32->next; bNodeSocket *in_socket_color4f = in_socket_vector->next; bNodeSocket *in_socket_bool = in_socket_color4f->next; + bNodeSocket *in_socket_quat = in_socket_bool->next; bke::nodeSetSocketAvailability(ntree, in_socket_vector, data_type == CD_PROP_FLOAT3); bke::nodeSetSocketAvailability(ntree, in_socket_float, data_type == CD_PROP_FLOAT); bke::nodeSetSocketAvailability(ntree, in_socket_color4f, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, in_socket_bool, data_type == CD_PROP_BOOL); bke::nodeSetSocketAvailability(ntree, in_socket_int32, data_type == CD_PROP_INT32); + bke::nodeSetSocketAvailability(ntree, in_socket_quat, data_type == CD_PROP_QUATERNION); bNodeSocket *out_socket_float = static_cast(node->outputs.first); bNodeSocket *out_socket_int32 = out_socket_float->next; bNodeSocket *out_socket_vector = out_socket_int32->next; bNodeSocket *out_socket_color4f = out_socket_vector->next; bNodeSocket *out_socket_bool = out_socket_color4f->next; + bNodeSocket *out_socket_quat = out_socket_bool->next; bke::nodeSetSocketAvailability(ntree, out_socket_vector, data_type == CD_PROP_FLOAT3); bke::nodeSetSocketAvailability(ntree, out_socket_float, data_type == CD_PROP_FLOAT); bke::nodeSetSocketAvailability(ntree, out_socket_color4f, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, out_socket_bool, data_type == CD_PROP_BOOL); bke::nodeSetSocketAvailability(ntree, out_socket_int32, data_type == CD_PROP_INT32); + bke::nodeSetSocketAvailability(ntree, out_socket_quat, data_type == CD_PROP_QUATERNION); } static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc index 0d59f52cadf..08d57ffed79 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc @@ -30,6 +30,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input("Value", "Value_Vector").hide_value().field_on_all(); b.add_input("Value", "Value_Color").hide_value().field_on_all(); b.add_input("Value", "Value_Bool").hide_value().field_on_all(); + b.add_input("Value", "Value_Rotation").hide_value().field_on_all(); b.add_input("Sample Position").implicit_field(implicit_field_inputs::position); @@ -38,6 +39,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_output("Value", "Value_Vector").dependent_field({6}); b.add_output("Value", "Value_Color").dependent_field({6}); b.add_output("Value", "Value_Bool").dependent_field({6}); + b.add_output("Value", "Value_Rotation").dependent_field({6}); } static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) @@ -60,24 +62,28 @@ static void node_update(bNodeTree *ntree, bNode *node) bNodeSocket *in_socket_vector = in_socket_int32->next; bNodeSocket *in_socket_color4f = in_socket_vector->next; bNodeSocket *in_socket_bool = in_socket_color4f->next; + bNodeSocket *in_socket_quat = in_socket_bool->next; bke::nodeSetSocketAvailability(ntree, in_socket_vector, data_type == CD_PROP_FLOAT3); bke::nodeSetSocketAvailability(ntree, in_socket_float, data_type == CD_PROP_FLOAT); bke::nodeSetSocketAvailability(ntree, in_socket_color4f, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, in_socket_bool, data_type == CD_PROP_BOOL); bke::nodeSetSocketAvailability(ntree, in_socket_int32, data_type == CD_PROP_INT32); + bke::nodeSetSocketAvailability(ntree, in_socket_quat, data_type == CD_PROP_QUATERNION); bNodeSocket *out_socket_float = static_cast(node->outputs.first); bNodeSocket *out_socket_int32 = out_socket_float->next; bNodeSocket *out_socket_vector = out_socket_int32->next; bNodeSocket *out_socket_color4f = out_socket_vector->next; bNodeSocket *out_socket_bool = out_socket_color4f->next; + bNodeSocket *out_socket_quat = out_socket_bool->next; bke::nodeSetSocketAvailability(ntree, out_socket_vector, data_type == CD_PROP_FLOAT3); bke::nodeSetSocketAvailability(ntree, out_socket_float, data_type == CD_PROP_FLOAT); bke::nodeSetSocketAvailability(ntree, out_socket_color4f, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, out_socket_bool, data_type == CD_PROP_BOOL); bke::nodeSetSocketAvailability(ntree, out_socket_int32, data_type == CD_PROP_INT32); + bke::nodeSetSocketAvailability(ntree, out_socket_quat, data_type == CD_PROP_QUATERNION); } static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) @@ -162,6 +168,8 @@ static GField get_input_attribute_field(GeoNodeExecParams ¶ms, const eCustom return params.extract_input>("Value_Bool"); case CD_PROP_INT32: return params.extract_input>("Value_Int"); + case CD_PROP_QUATERNION: + return params.extract_input>("Value_Rotation"); default: BLI_assert_unreachable(); } @@ -191,6 +199,10 @@ static void output_attribute_field(GeoNodeExecParams ¶ms, GField field) params.set_output("Value_Int", Field(field)); break; } + case CD_PROP_QUATERNION: { + params.set_output("Value_Rotation", Field(field)); + break; + } default: break; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_uv_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_uv_surface.cc index e1d81c21d55..84e284a41f8 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sample_uv_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_uv_surface.cc @@ -29,6 +29,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input("Value", "Value_Vector").hide_value().field_on_all(); b.add_input("Value", "Value_Color").hide_value().field_on_all(); b.add_input("Value", "Value_Bool").hide_value().field_on_all(); + b.add_input("Value", "Value_Rotation").hide_value().field_on_all(); b.add_input("Source UV Map") .hide_value() @@ -43,6 +44,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_output("Value", "Value_Vector").dependent_field({7}); b.add_output("Value", "Value_Color").dependent_field({7}); b.add_output("Value", "Value_Bool").dependent_field({7}); + b.add_output("Value", "Value_Rotation").dependent_field({7}); b.add_output("Is Valid") .dependent_field({7}) @@ -69,24 +71,28 @@ static void node_update(bNodeTree *ntree, bNode *node) bNodeSocket *in_socket_vector = in_socket_int32->next; bNodeSocket *in_socket_color4f = in_socket_vector->next; bNodeSocket *in_socket_bool = in_socket_color4f->next; + bNodeSocket *in_socket_quat = in_socket_bool->next; bke::nodeSetSocketAvailability(ntree, in_socket_vector, data_type == CD_PROP_FLOAT3); bke::nodeSetSocketAvailability(ntree, in_socket_float, data_type == CD_PROP_FLOAT); bke::nodeSetSocketAvailability(ntree, in_socket_color4f, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, in_socket_bool, data_type == CD_PROP_BOOL); bke::nodeSetSocketAvailability(ntree, in_socket_int32, data_type == CD_PROP_INT32); + bke::nodeSetSocketAvailability(ntree, in_socket_quat, data_type == CD_PROP_QUATERNION); bNodeSocket *out_socket_float = static_cast(node->outputs.first); bNodeSocket *out_socket_int32 = out_socket_float->next; bNodeSocket *out_socket_vector = out_socket_int32->next; bNodeSocket *out_socket_color4f = out_socket_vector->next; bNodeSocket *out_socket_bool = out_socket_color4f->next; + bNodeSocket *out_socket_quat = out_socket_bool->next; bke::nodeSetSocketAvailability(ntree, out_socket_vector, data_type == CD_PROP_FLOAT3); bke::nodeSetSocketAvailability(ntree, out_socket_float, data_type == CD_PROP_FLOAT); bke::nodeSetSocketAvailability(ntree, out_socket_color4f, data_type == CD_PROP_COLOR); bke::nodeSetSocketAvailability(ntree, out_socket_bool, data_type == CD_PROP_BOOL); bke::nodeSetSocketAvailability(ntree, out_socket_int32, data_type == CD_PROP_INT32); + bke::nodeSetSocketAvailability(ntree, out_socket_quat, data_type == CD_PROP_QUATERNION); } static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) @@ -188,6 +194,8 @@ static GField get_input_attribute_field(GeoNodeExecParams ¶ms, const eCustom return params.extract_input>("Value_Bool"); case CD_PROP_INT32: return params.extract_input>("Value_Int"); + case CD_PROP_QUATERNION: + return params.extract_input>("Value_Rotation"); default: BLI_assert_unreachable(); } @@ -217,6 +225,10 @@ static void output_attribute_field(GeoNodeExecParams ¶ms, GField field) params.set_output("Value_Int", Field(field)); break; } + case CD_PROP_QUATERNION: { + params.set_output("Value_Rotation", Field(field)); + break; + } default: break; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_simulation_output.cc b/source/blender/nodes/geometry/nodes/node_geo_simulation_output.cc index 09638865143..2476816e34c 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_simulation_output.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_simulation_output.cc @@ -64,6 +64,11 @@ static std::unique_ptr socket_declaration_for_simulation_item decl->input_field_type = InputSocketFieldType::IsSupported; decl->output_field_dependency = OutputFieldDependency::ForPartiallyDependentField({index}); break; + case SOCK_ROTATION: + decl = std::make_unique(); + decl->input_field_type = InputSocketFieldType::IsSupported; + decl->output_field_dependency = OutputFieldDependency::ForPartiallyDependentField({index}); + break; case SOCK_INT: decl = std::make_unique(); decl->input_field_type = InputSocketFieldType::IsSupported; @@ -214,6 +219,7 @@ void simulation_state_to_values(const Span node_simulation_i case SOCK_VECTOR: case SOCK_INT: case SOCK_BOOLEAN: + case SOCK_ROTATION: case SOCK_RGBA: { const fn::ValueOrFieldCPPType &value_or_field_type = *fn::ValueOrFieldCPPType::get_from_self(cpp_type); @@ -311,6 +317,7 @@ void values_to_simulation_state(const Span node_simulation_i case SOCK_VECTOR: case SOCK_INT: case SOCK_BOOLEAN: + case SOCK_ROTATION: case SOCK_RGBA: { const CPPType &type = get_simulation_item_cpp_type(item); const fn::ValueOrFieldCPPType &value_or_field_type = @@ -616,6 +623,7 @@ static void mix_simulation_state(const NodeSimulationItem &item, case SOCK_VECTOR: case SOCK_INT: case SOCK_BOOLEAN: + case SOCK_ROTATION: case SOCK_RGBA: { const CPPType &type = get_simulation_item_cpp_type(item); const fn::ValueOrFieldCPPType &value_or_field_type = *fn::ValueOrFieldCPPType::get_from_self( @@ -1005,6 +1013,7 @@ bool NOD_geometry_simulation_output_item_socket_type_supported( SOCK_VECTOR, SOCK_RGBA, SOCK_BOOLEAN, + SOCK_ROTATION, SOCK_INT, SOCK_STRING, SOCK_GEOMETRY); diff --git a/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc index 51c8860b746..2adc0cffba0 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc @@ -29,6 +29,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input("Value", "Value_Color").field_on_all(); b.add_input("Value", "Value_Bool").field_on_all(); b.add_input("Value", "Value_Int").field_on_all(); + b.add_input("Value", "Value_Rotation").field_on_all(); b.add_output("Geometry").propagate_all(); } @@ -61,6 +62,7 @@ static void node_update(bNodeTree *ntree, bNode *node) bNodeSocket *socket_color4f = socket_float->next; bNodeSocket *socket_boolean = socket_color4f->next; bNodeSocket *socket_int32 = socket_boolean->next; + bNodeSocket *socket_quat = socket_int32->next; bke::nodeSetSocketAvailability( ntree, socket_vector, ELEM(data_type, CD_PROP_FLOAT2, CD_PROP_FLOAT3)); @@ -69,6 +71,7 @@ static void node_update(bNodeTree *ntree, bNode *node) ntree, socket_color4f, ELEM(data_type, CD_PROP_COLOR, CD_PROP_BYTE_COLOR)); bke::nodeSetSocketAvailability(ntree, socket_boolean, data_type == CD_PROP_BOOL); bke::nodeSetSocketAvailability(ntree, socket_int32, data_type == CD_PROP_INT32); + bke::nodeSetSocketAvailability(ntree, socket_quat, data_type == CD_PROP_QUATERNION); } static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) @@ -142,6 +145,9 @@ static void node_geo_exec(GeoNodeExecParams params) case CD_PROP_INT32: field = params.get_input>("Value_Int"); break; + case CD_PROP_QUATERNION: + field = params.get_input>("Value_Rotation"); + break; default: break; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_switch.cc b/source/blender/nodes/geometry/nodes/node_geo_switch.cc index 57de95c3920..893ff45162c 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_switch.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_switch.cc @@ -50,6 +50,8 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input("True", "True_010"); b.add_input("False", "False_011"); b.add_input("True", "True_011"); + b.add_input("False", "False_012").supports_field(); + b.add_input("True", "True_012").supports_field(); b.add_output("Output").dependent_field().reference_pass_all(); b.add_output("Output", "Output_001").dependent_field().reference_pass_all(); @@ -63,6 +65,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_output("Output", "Output_009"); b.add_output("Output", "Output_010"); b.add_output("Output", "Output_011"); + b.add_output("Output", "Output_012").propagate_all().reference_pass_all(); } static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) @@ -84,8 +87,14 @@ static void node_update(bNodeTree *ntree, bNode *node) bNodeSocket *field_switch = static_cast(node->inputs.first); bNodeSocket *non_field_switch = static_cast(field_switch->next); - const bool fields_type = ELEM( - storage.input_type, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, SOCK_VECTOR, SOCK_RGBA, SOCK_STRING); + const bool fields_type = ELEM(storage.input_type, + SOCK_FLOAT, + SOCK_INT, + SOCK_BOOLEAN, + SOCK_VECTOR, + SOCK_RGBA, + SOCK_STRING, + SOCK_ROTATION); bke::nodeSetSocketAvailability(ntree, field_switch, fields_type); bke::nodeSetSocketAvailability(ntree, non_field_switch, !fields_type); @@ -150,7 +159,8 @@ class LazyFunctionForSwitchNode : public LazyFunction { { const NodeSwitch &storage = node_storage(node); const eNodeSocketDatatype data_type = eNodeSocketDatatype(storage.input_type); - can_be_field_ = ELEM(data_type, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, SOCK_VECTOR, SOCK_RGBA); + can_be_field_ = ELEM( + data_type, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, SOCK_VECTOR, SOCK_RGBA, SOCK_ROTATION); const bNodeSocketType *socket_type = nullptr; for (const bNodeSocket *socket : node.output_sockets()) { @@ -236,20 +246,25 @@ class LazyFunctionForSwitchNode : public LazyFunction { const MultiFunction &get_switch_multi_function(const CPPType &type) const { const MultiFunction *switch_multi_function = nullptr; - type.to_static_type_tag( - [&](auto type_tag) { - using T = typename decltype(type_tag)::type; - if constexpr (std::is_void_v) { - BLI_assert_unreachable(); - } - else { - static auto switch_fn = mf::build::SI3_SO( - "Switch", [](const bool condition, const T &false_value, const T &true_value) { - return condition ? true_value : false_value; - }); - switch_multi_function = &switch_fn; - } - }); + type.to_static_type_tag([&](auto type_tag) { + using T = typename decltype(type_tag)::type; + if constexpr (std::is_void_v) { + BLI_assert_unreachable(); + } + else { + static auto switch_fn = mf::build::SI3_SO( + "Switch", [](const bool condition, const T &false_value, const T &true_value) { + return condition ? true_value : false_value; + }); + switch_multi_function = &switch_fn; + } + }); BLI_assert(switch_multi_function != nullptr); return *switch_multi_function; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_viewer.cc b/source/blender/nodes/geometry/nodes/node_geo_viewer.cc index 5f70684ebd5..c36ae1797c8 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_viewer.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_viewer.cc @@ -26,6 +26,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input("Value", "Value_002").field_on_all().hide_value(); b.add_input("Value", "Value_003").field_on_all().hide_value(); b.add_input("Value", "Value_004").field_on_all().hide_value(); + b.add_input("Value", "Value_005").field_on_all().hide_value(); } static void node_init(bNodeTree * /*tree*/, bNode *node) @@ -60,6 +61,8 @@ static eNodeSocketDatatype custom_data_type_to_socket_type(const eCustomDataType return SOCK_BOOLEAN; case CD_PROP_COLOR: return SOCK_RGBA; + case CD_PROP_QUATERNION: + return SOCK_ROTATION; default: BLI_assert_unreachable(); return SOCK_FLOAT; @@ -103,8 +106,14 @@ static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) set_active_fn(params, node); }); } - if (type && - ELEM(type, CD_PROP_FLOAT, CD_PROP_BOOL, CD_PROP_INT32, CD_PROP_FLOAT3, CD_PROP_COLOR)) { + if (type && ELEM(type, + CD_PROP_FLOAT, + CD_PROP_BOOL, + CD_PROP_INT32, + CD_PROP_FLOAT3, + CD_PROP_COLOR, + CD_PROP_QUATERNION)) + { params.add_item(IFACE_("Value"), [type, set_active_fn](LinkSearchOpParams ¶ms) { bNode &node = params.add_node("GeometryNodeViewer"); node_storage(node).data_type = *type; diff --git a/source/blender/nodes/intern/geometry_nodes_execute.cc b/source/blender/nodes/intern/geometry_nodes_execute.cc index 6cc993eb106..b3ec6ca1dae 100644 --- a/source/blender/nodes/intern/geometry_nodes_execute.cc +++ b/source/blender/nodes/intern/geometry_nodes_execute.cc @@ -4,6 +4,8 @@ * \ingroup nodes */ +#include "BLI_math_quaternion.hh" + #include "NOD_geometry_nodes_execute.hh" #include "NOD_geometry_nodes_lazy_function.hh" #include "NOD_node_declaration.hh" @@ -115,6 +117,9 @@ std::unique_ptr id_property_create_f ui_data->default_value = value->value != 0; return property; } + case SOCK_ROTATION: { + return nullptr; + } case SOCK_STRING: { const bNodeSocketValueString *value = static_cast( socket.default_value); @@ -166,6 +171,7 @@ bool id_property_type_matches_socket(const bNodeSocket &socket, const IDProperty case SOCK_VECTOR: return property.type == IDP_ARRAY && property.subtype == IDP_FLOAT && property.len == 3; case SOCK_RGBA: + case SOCK_ROTATION: return property.type == IDP_ARRAY && property.subtype == IDP_FLOAT && property.len == 4; case SOCK_BOOLEAN: return property.type == IDP_BOOLEAN; @@ -218,6 +224,12 @@ static void init_socket_cpp_value_from_property(const IDProperty &property, new (r_value) fn::ValueOrField(value); break; } + case SOCK_ROTATION: { + const math::Quaternion value = math::Quaternion( + float4(static_cast(IDP_Array(&property)))); + new (r_value) fn::ValueOrField(value); + break; + } case SOCK_STRING: { std::string value = IDP_String(&property); new (r_value) fn::ValueOrField(std::move(value)); -- 2.30.2 From 8928b3a5cb37be591eb98c962e4b4315bf161a0a Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 15 May 2023 17:16:52 -0400 Subject: [PATCH 4/4] Geometry Nodes: Use rotation socket in instance and transform nodes --- .../geometry/nodes/node_geo_instance_on_points.cc | 12 ++++-------- .../geometry/nodes/node_geo_transform_geometry.cc | 9 +++++---- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc index c450028239f..34085497f7f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc @@ -34,10 +34,7 @@ static void node_declare(NodeDeclarationBuilder &b) .description( "Index of the instance used for each point. This is only used when Pick Instances " "is on. By default the point index is used"); - b.add_input("Rotation") - .subtype(PROP_EULER) - .field_on({0}) - .description("Rotation of the instances"); + b.add_input("Rotation").field_on({0}).description("Rotation of the instances"); b.add_input("Scale") .default_value({1.0f, 1.0f, 1.0f}) .subtype(PROP_XYZ) @@ -59,7 +56,7 @@ static void add_instances_from_component( VArray pick_instance; VArray indices; - VArray rotations; + VArray rotations; VArray scales; const bke::GeometryFieldContext field_context{src_component, domain}; @@ -70,7 +67,7 @@ static void add_instances_from_component( * selected indices should be copied. */ evaluator.add(params.get_input>("Pick Instance"), &pick_instance); evaluator.add(params.get_input>("Instance Index"), &indices); - evaluator.add(params.get_input>("Rotation"), &rotations); + evaluator.add(params.get_input>("Rotation"), &rotations); evaluator.add(params.get_input>("Scale"), &scales); evaluator.evaluate(); @@ -118,8 +115,7 @@ static void add_instances_from_component( /* Compute base transform for every instances. */ float4x4 &dst_transform = dst_transforms[range_i]; - dst_transform = math::from_loc_rot_scale( - positions[i], math::EulerXYZ(rotations[i]), scales[i]); + dst_transform = math::from_loc_rot_scale(positions[i], rotations[i], scales[i]); /* Reference that will be used by this new instance. */ int dst_handle = empty_reference_handle; diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_transform_geometry.cc index 15ad19b9d99..ba949a62c97 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_transform_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_transform_geometry.cc @@ -8,6 +8,7 @@ #include "BLI_math_matrix.hh" #include "BLI_math_matrix_types.hh" +#include "BLI_math_quaternion.hh" #include "BLI_task.hh" #include "DNA_mesh_types.h" @@ -26,9 +27,9 @@ namespace blender::nodes { -static bool use_translate(const float3 rotation, const float3 scale) +static bool use_translate(const math::Quaternion rotation, const float3 scale) { - if (compare_ff(math::length_squared(rotation), 0.0f, 1e-9f) != 1) { + if (!math::is_equal(float4(rotation), float4(math::Quaternion::identity()), 1e7f)) { return false; } if (compare_ff(scale.x, 1.0f, 1e-9f) != 1 || compare_ff(scale.y, 1.0f, 1e-9f) != 1 || @@ -267,7 +268,7 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_input("Geometry"); b.add_input("Translation").subtype(PROP_TRANSLATION); - b.add_input("Rotation").subtype(PROP_EULER); + b.add_input("Rotation"); b.add_input("Scale").default_value({1, 1, 1}).subtype(PROP_XYZ); b.add_output("Geometry").propagate_all(); } @@ -276,7 +277,7 @@ static void node_geo_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input("Geometry"); const float3 translation = params.extract_input("Translation"); - const float3 rotation = params.extract_input("Rotation"); + const math::Quaternion rotation = params.extract_input("Rotation"); const float3 scale = params.extract_input("Scale"); /* Use only translation if rotation and scale don't apply. */ -- 2.30.2