WIP: Geometry Nodes: Rotation type #107954

Closed
Hans Goudey wants to merge 4 commits from HooglyBoogly:geometry-nodes-rotation-type into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
14 changed files with 248 additions and 3 deletions
Showing only changes of commit 4a52f75e58 - Show all commits

View File

@ -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<bNodeSocketValueMaterial>()->value;
case SOCK_STRING:
case SOCK_ROTATION:
/* We don't want do this now! */
return nullptr;
case SOCK_CUSTOM:

View File

@ -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)

View File

@ -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:

View File

@ -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;

View File

@ -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:

View File

@ -391,6 +391,9 @@ static Vector<NodeLinkItem> ui_node_link_items(NodeLinkArg *arg,
else if (dynamic_cast<const decl::Color *>(&socket_decl)) {
item.socket_type = SOCK_RGBA;
}
else if (dynamic_cast<const decl::Rotation *>(&socket_decl)) {
item.socket_type = SOCK_ROTATION;
}
else if (dynamic_cast<const decl::String *>(&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);

View File

@ -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;

View File

@ -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,

View File

@ -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<typename T>
static inline constexpr bool is_field_base_type_v =
is_same_any_v<T, float, int, bool, ColorGeometry4f, float3, std::string>;
is_same_any_v<T, float, int, bool, ColorGeometry4f, float3, std::string, math::Quaternion>;
/**
* Get the input value for the input socket with the given identifier.

View File

@ -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<Color> {
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<Rotation> {
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
* \{ */

View File

@ -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,

View File

@ -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<bNodeSocketValueRotation>();
std::unique_ptr<decl::Rotation> decl = std::make_unique<decl::Rotation>();
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<bNodeSocketValueInt>();
std::unique_ptr<decl::Int> decl = std::make_unique<decl::Int>();

View File

@ -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<bNodeSocketValueRotation>(__func__);
sock->default_value = dval;
break;
}
case SOCK_VECTOR: {
static float default_value[] = {0.0f, 0.0f, 0.0f};
bNodeSocketValueVector *dval = MEM_cnew<bNodeSocketValueVector>("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<math::Quaternion>();
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
const auto &value = *socket.default_value_typed<bNodeSocketValueRotation>();
const math::EulerXYZ euler(float3(value.value_euler));
*static_cast<math::Quaternion *>(r_value) = math::to_quaternion(euler);
};
socktype->geometry_nodes_cpp_type = &blender::CPPType::get<ValueOrField<math::Quaternion>>();
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<math::Quaternion>(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));

View File

@ -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<bNodeSocketValueRotation *>(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;
}
/** \} */
/* -------------------------------------------------------------------- */