Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2021-09-28 20:05:42 +0300
committerHans Goudey <h.goudey@me.com>2021-09-28 20:05:42 +0300
commit797064544ea3e176c511f7ff7c1303498a783182 (patch)
treeee3cef6afe9024da7e1496361a7b7a0bb62f93ae
parent44e4f077a9d7b5b609f6199874802675d75f7266 (diff)
Geometry Nodes: Only show attribute toggle for field inputs
Change the toggle to switch between an attribute and a single value to only display for inputs that are fields, as determined statically by the field inferencing added in rB61f3d4eb7c7db7. This means the field inferencing must be calculated on file load, since it's used in the UI. Differential Revision: https://developer.blender.org/D12623
-rw-r--r--source/blender/blenkernel/intern/node.cc24
-rw-r--r--source/blender/makesdna/DNA_node_types.h10
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc67
-rw-r--r--source/blender/nodes/NOD_node_declaration.hh18
4 files changed, 76 insertions, 43 deletions
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index f2843e5f88e..c8ba7991f31 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -104,6 +104,7 @@ using blender::Span;
using blender::Stack;
using blender::Vector;
using blender::VectorSet;
+using blender::nodes::FieldInferencingInterface;
using blender::nodes::InputSocketFieldType;
using blender::nodes::NodeDeclaration;
using blender::nodes::OutputFieldDependency;
@@ -823,6 +824,11 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
/* TODO: should be dealt by new generic cache handling of IDs... */
ntree->previews = nullptr;
+ if (ntree->type == NTREE_GEOMETRY) {
+ /* Update field referencing for the geometry nodes modifier. */
+ ntree->update |= NTREE_UPDATE_FIELD_INFERENCING;
+ }
+
/* type verification is in lib-link */
}
@@ -4456,24 +4462,6 @@ void ntreeUpdateAllNew(Main *main)
FOREACH_NODETREE_END;
}
-/**
- * Information about how a node interacts with fields.
- */
-struct FieldInferencingInterface {
- Vector<InputSocketFieldType> inputs;
- Vector<OutputFieldDependency> outputs;
-
- friend bool operator==(const FieldInferencingInterface &a, const FieldInferencingInterface &b)
- {
- return a.inputs == b.inputs && a.outputs == b.outputs;
- }
-
- friend bool operator!=(const FieldInferencingInterface &a, const FieldInferencingInterface &b)
- {
- return !(a == b);
- }
-};
-
static FieldInferencingInterface *node_field_inferencing_interface_copy(
const FieldInferencingInterface &field_inferencing_interface)
{
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 34c74e5bd88..f7f2ccaa7be 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -463,7 +463,15 @@ typedef struct bNodeLink {
#define NTREE_CHUNKSIZE_512 512
#define NTREE_CHUNKSIZE_1024 1024
+/** Workaround to forward-declare C++ type in C header. */
+#ifdef __cplusplus
+namespace blender::nodes {
struct FieldInferencingInterface;
+}
+using FieldInferencingInterfaceHandle = blender::nodes::FieldInferencingInterface;
+#else
+typedef struct FieldInferencingInterfaceHandle FieldInferencingInterfaceHandle;
+#endif
/* the basis for a Node tree, all links and nodes reside internal here */
/* only re-usable node trees are in the library though,
@@ -488,7 +496,7 @@ typedef struct bNodeTree {
ListBase nodes, links;
/** Information about how inputs and outputs of the node group interact with fields. */
- struct FieldInferencingInterface *field_inferencing_interface;
+ FieldInferencingInterfaceHandle *field_inferencing_interface;
/** Set init on fileread. */
int type, init;
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index d5dcf88b914..f2f9b82480d 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -88,6 +88,7 @@
#include "NOD_derived_node_tree.hh"
#include "NOD_geometry.h"
#include "NOD_geometry_nodes_eval_log.hh"
+#include "NOD_node_declaration.hh"
#include "FN_field.hh"
#include "FN_multi_function.hh"
@@ -107,7 +108,9 @@ using blender::bke::OutputAttribute;
using blender::fn::GField;
using blender::fn::GMutablePointer;
using blender::fn::GPointer;
+using blender::nodes::FieldInferencingInterface;
using blender::nodes::GeoNodeExecParams;
+using blender::nodes::InputSocketFieldType;
using blender::threading::EnumerableThreadSpecific;
using namespace blender::fn::multi_function_types;
using namespace blender::nodes::derived_node_tree_types;
@@ -308,6 +311,17 @@ static bool socket_type_has_attribute_toggle(const bNodeSocket &socket)
return ELEM(socket.type, SOCK_FLOAT, SOCK_VECTOR, SOCK_BOOLEAN, SOCK_RGBA, SOCK_INT);
}
+/**
+ * \return Whether using an attribute to input values of this type is supported, and the node
+ * group's input for this socket accepts a field rather than just single values.
+ */
+static bool input_has_attribute_toggle(const bNodeTree &node_tree, const int socket_index)
+{
+ BLI_assert(node_tree.field_inferencing_interface != nullptr);
+ const FieldInferencingInterface &field_interface = *node_tree.field_inferencing_interface;
+ return field_interface.inputs[socket_index] != InputSocketFieldType::None;
+}
+
static IDProperty *id_property_create_from_socket(const bNodeSocket &socket)
{
switch (socket.type) {
@@ -533,7 +547,8 @@ void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd)
nmd->settings.properties = IDP_New(IDP_GROUP, &idprop, "Nodes Modifier Settings");
}
- LISTBASE_FOREACH (bNodeSocket *, socket, &nmd->node_group->inputs) {
+ int socket_index;
+ LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, &nmd->node_group->inputs, socket_index) {
IDProperty *new_prop = id_property_create_from_socket(*socket);
if (new_prop == nullptr) {
/* Out of the set of supported input sockets, only
@@ -564,7 +579,7 @@ void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd)
}
}
- if (socket_type_has_attribute_toggle(*socket)) {
+ if (input_has_attribute_toggle(*nmd->node_group, socket_index)) {
const std::string use_attribute_id = socket->identifier + use_attribute_suffix;
const std::string attribute_name_id = socket->identifier + attribute_name_suffix;
@@ -655,37 +670,39 @@ void MOD_nodes_init(Main *bmain, NodesModifierData *nmd)
}
static void initialize_group_input(NodesModifierData &nmd,
- const bNodeSocket &socket,
+ const OutputSocketRef &socket,
void *r_value)
{
+ const bNodeSocketType &socket_type = *socket.typeinfo();
+ const bNodeSocket &bsocket = *socket.bsocket();
if (nmd.settings.properties == nullptr) {
- socket.typeinfo->get_geometry_nodes_cpp_value(socket, r_value);
+ socket_type.get_geometry_nodes_cpp_value(bsocket, r_value);
return;
}
const IDProperty *property = IDP_GetPropertyFromGroup(nmd.settings.properties,
- socket.identifier);
+ socket.identifier().c_str());
if (property == nullptr) {
- socket.typeinfo->get_geometry_nodes_cpp_value(socket, r_value);
+ socket_type.get_geometry_nodes_cpp_value(bsocket, r_value);
return;
}
- if (!id_property_type_matches_socket(socket, *property)) {
- socket.typeinfo->get_geometry_nodes_cpp_value(socket, r_value);
+ if (!id_property_type_matches_socket(bsocket, *property)) {
+ socket_type.get_geometry_nodes_cpp_value(bsocket, r_value);
return;
}
- if (!socket_type_has_attribute_toggle(socket)) {
+ if (!input_has_attribute_toggle(*nmd.node_group, socket.index())) {
init_socket_cpp_value_from_property(
- *property, static_cast<eNodeSocketDatatype>(socket.type), r_value);
+ *property, static_cast<eNodeSocketDatatype>(bsocket.type), r_value);
return;
}
const IDProperty *property_use_attribute = IDP_GetPropertyFromGroup(
- nmd.settings.properties, (socket.identifier + use_attribute_suffix).c_str());
+ nmd.settings.properties, (socket.identifier() + use_attribute_suffix).c_str());
const IDProperty *property_attribute_name = IDP_GetPropertyFromGroup(
- nmd.settings.properties, (socket.identifier + attribute_name_suffix).c_str());
+ nmd.settings.properties, (socket.identifier() + attribute_name_suffix).c_str());
if (property_use_attribute == nullptr || property_attribute_name == nullptr) {
init_socket_cpp_value_from_property(
- *property, static_cast<eNodeSocketDatatype>(socket.type), r_value);
+ *property, static_cast<eNodeSocketDatatype>(bsocket.type), r_value);
return;
}
@@ -693,12 +710,12 @@ static void initialize_group_input(NodesModifierData &nmd,
if (use_attribute) {
const StringRef attribute_name{IDP_String(property_attribute_name)};
auto attribute_input = std::make_shared<blender::bke::AttributeFieldInput>(
- attribute_name, *socket.typeinfo->get_base_cpp_type());
+ attribute_name, *socket_type.get_base_cpp_type());
new (r_value) blender::fn::GField(std::move(attribute_input), 0);
}
else {
init_socket_cpp_value_from_property(
- *property, static_cast<eNodeSocketDatatype>(socket.type), r_value);
+ *property, static_cast<eNodeSocketDatatype>(bsocket.type), r_value);
}
}
@@ -914,7 +931,7 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree,
for (const OutputSocketRef *socket : remaining_input_sockets) {
const CPPType &cpp_type = *socket->typeinfo()->get_geometry_nodes_cpp_type();
void *value_in = allocator.allocate(cpp_type.size(), cpp_type.alignment());
- initialize_group_input(*nmd, *socket->bsocket(), value_in);
+ initialize_group_input(*nmd, *socket, value_in);
group_inputs.add_new({root_context, socket}, {cpp_type, value_in});
}
}
@@ -1079,11 +1096,12 @@ static void modifyGeometrySet(ModifierData *md,
/* Drawing the properties manually with #uiItemR instead of #uiDefAutoButsRNA allows using
* the node socket identifier for the property names, since they are unique, but also having
* the correct label displayed in the UI. */
-static void draw_property_for_input_socket(uiLayout *layout,
- NodesModifierData *nmd,
- PointerRNA *bmain_ptr,
- PointerRNA *md_ptr,
- const bNodeSocket &socket)
+static void draw_property_for_socket(uiLayout *layout,
+ NodesModifierData *nmd,
+ PointerRNA *bmain_ptr,
+ PointerRNA *md_ptr,
+ const bNodeSocket &socket,
+ const int socket_index)
{
/* The property should be created in #MOD_nodes_update_interface with the correct type. */
IDProperty *property = IDP_GetPropertyFromGroup(nmd->settings.properties, socket.identifier);
@@ -1128,7 +1146,7 @@ static void draw_property_for_input_socket(uiLayout *layout,
break;
}
default: {
- if (socket_type_has_attribute_toggle(socket) &&
+ if (input_has_attribute_toggle(*nmd->node_group, socket_index) &&
USER_EXPERIMENTAL_TEST(&U, use_geometry_nodes_fields)) {
const std::string rna_path_use_attribute = "[\"" + std::string(socket_id_esc) +
use_attribute_suffix + "\"]";
@@ -1200,8 +1218,9 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA bmain_ptr;
RNA_main_pointer_create(bmain, &bmain_ptr);
- LISTBASE_FOREACH (bNodeSocket *, socket, &nmd->node_group->inputs) {
- draw_property_for_input_socket(layout, nmd, &bmain_ptr, ptr, *socket);
+ int socket_index;
+ LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, &nmd->node_group->inputs, socket_index) {
+ draw_property_for_socket(layout, nmd, &bmain_ptr, ptr, *socket, socket_index);
}
}
diff --git a/source/blender/nodes/NOD_node_declaration.hh b/source/blender/nodes/NOD_node_declaration.hh
index 8c7d343c001..07d4e05cda8 100644
--- a/source/blender/nodes/NOD_node_declaration.hh
+++ b/source/blender/nodes/NOD_node_declaration.hh
@@ -113,6 +113,24 @@ class OutputFieldDependency {
};
/**
+ * Information about how a node interacts with fields.
+ */
+struct FieldInferencingInterface {
+ Vector<InputSocketFieldType> inputs;
+ Vector<OutputFieldDependency> outputs;
+
+ friend bool operator==(const FieldInferencingInterface &a, const FieldInferencingInterface &b)
+ {
+ return a.inputs == b.inputs && a.outputs == b.outputs;
+ }
+
+ friend bool operator!=(const FieldInferencingInterface &a, const FieldInferencingInterface &b)
+ {
+ return !(a == b);
+ }
+};
+
+/**
* Describes a single input or output socket. This is subclassed for different socket types.
*/
class SocketDeclaration {