[Bf-blender-cvs] [4a5f36638b0] master: Geometry Nodes: simplify supporting different input socket types for attributes

Jacques Lucke noreply at git.blender.org
Wed Dec 9 16:29:45 CET 2020


Commit: 4a5f36638b0244b586607e76451669ffbc3c1174
Author: Jacques Lucke
Date:   Wed Dec 9 16:20:48 2020 +0100
Branches: master
https://developer.blender.org/rB4a5f36638b0244b586607e76451669ffbc3c1174

Geometry Nodes: simplify supporting different input socket types for attributes

This is a non-functional change. The functionality introduced in this commit
is not used in master yet. It is used by nodes that are being developed in
other branches though.

===================================================================

M	source/blender/blenkernel/BKE_geometry_set.hh
M	source/blender/blenkernel/intern/attribute_access.cc
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/nodes/NOD_geometry_exec.hh
M	source/blender/nodes/geometry/node_geometry_util.cc
M	source/blender/nodes/geometry/node_geometry_util.hh
M	source/blender/nodes/intern/node_geometry_exec.cc

===================================================================

diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index ef3ae3c381c..3398da9896b 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -157,6 +157,14 @@ class GeometryComponent {
                                                                  const CustomDataType data_type,
                                                                  const void *value) const;
 
+  /* Create a read-only dummy attribute that always returns the same value.
+   * The given value is converted to the correct type if necessary. */
+  blender::bke::ReadAttributePtr attribute_get_constant_for_read_converted(
+      const AttributeDomain domain,
+      const CustomDataType in_data_type,
+      const CustomDataType out_data_type,
+      const void *value) const;
+
   /* Get a read-only dummy attribute that always returns the same value. */
   template<typename T>
   blender::bke::TypedReadAttribute<T> attribute_get_constant_for_read(const AttributeDomain domain,
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index 9f5795291f0..d79168d5443 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -668,6 +668,39 @@ blender::bke::ReadAttributePtr GeometryComponent::attribute_get_constant_for_rea
       domain, domain_size, *cpp_type, value);
 }
 
+blender::bke::ReadAttributePtr GeometryComponent::attribute_get_constant_for_read_converted(
+    const AttributeDomain domain,
+    const CustomDataType in_data_type,
+    const CustomDataType out_data_type,
+    const void *value) const
+{
+  BLI_assert(this->attribute_domain_supported(domain));
+  if (value == nullptr || in_data_type == out_data_type) {
+    return this->attribute_get_constant_for_read(domain, out_data_type, value);
+  }
+
+  const blender::fn::CPPType *in_cpp_type = blender::bke::custom_data_type_to_cpp_type(
+      in_data_type);
+  const blender::fn::CPPType *out_cpp_type = blender::bke::custom_data_type_to_cpp_type(
+      out_data_type);
+  BLI_assert(in_cpp_type != nullptr);
+  BLI_assert(out_cpp_type != nullptr);
+
+  const blender::nodes::DataTypeConversions &conversions =
+      blender::nodes::get_implicit_type_conversions();
+  BLI_assert(conversions.is_convertible(*in_cpp_type, *out_cpp_type));
+
+  void *out_value = alloca(out_cpp_type->size());
+  conversions.convert(*in_cpp_type, *out_cpp_type, value, out_value);
+
+  const int domain_size = this->attribute_domain_size(domain);
+  blender::bke::ReadAttributePtr attribute = std::make_unique<blender::bke::ConstantReadAttribute>(
+      domain, domain_size, *out_cpp_type, out_value);
+
+  out_cpp_type->destruct(out_value);
+  return attribute;
+}
+
 WriteAttributePtr GeometryComponent::attribute_try_ensure_for_write(const StringRef attribute_name,
                                                                     const AttributeDomain domain,
                                                                     const CustomDataType data_type)
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 29c83d2d4ed..13f8b11352a 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1464,6 +1464,13 @@ typedef enum GeometryNodeUseAttributeFlag {
   GEO_NODE_USE_ATTRIBUTE_B = (1 << 1),
 } GeometryNodeUseAttributeFlag;
 
+typedef enum GeometryNodeAttributeInputMode {
+  GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE = 0,
+  GEO_NODE_ATTRIBUTE_INPUT_FLOAT = 1,
+  GEO_NODE_ATTRIBUTE_INPUT_VECTOR = 2,
+  GEO_NODE_ATTRIBUTE_INPUT_COLOR = 3,
+} GeometryNodeAttributeInputMode;
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh
index fde576d7429..a7df4bc3e1b 100644
--- a/source/blender/nodes/NOD_geometry_exec.hh
+++ b/source/blender/nodes/NOD_geometry_exec.hh
@@ -148,6 +148,26 @@ class GeoNodeExecParams {
     return self_object_;
   }
 
+  /**
+   * Creates a read-only attribute based on node inputs. The method automatically detects which
+   * input with the given name is available.
+   */
+  ReadAttributePtr get_input_attribute(const StringRef name,
+                                       const GeometryComponent &component,
+                                       const AttributeDomain domain,
+                                       const CustomDataType type,
+                                       const void *default_value) const;
+
+  template<typename T>
+  bke::TypedReadAttribute<T> get_input_attribute(const StringRef name,
+                                                 const GeometryComponent &component,
+                                                 const AttributeDomain domain,
+                                                 const T &default_value) const
+  {
+    const CustomDataType type = bke::cpp_type_to_custom_data_type(CPPType::get<T>());
+    return this->get_input_attribute(name, component, domain, type, &default_value);
+  }
+
  private:
   /* Utilities for detecting common errors at when using this class. */
   void check_extract_input(StringRef identifier, const CPPType *requested_type = nullptr) const;
diff --git a/source/blender/nodes/geometry/node_geometry_util.cc b/source/blender/nodes/geometry/node_geometry_util.cc
index 41bdb1cfff0..34c7d224f03 100644
--- a/source/blender/nodes/geometry/node_geometry_util.cc
+++ b/source/blender/nodes/geometry/node_geometry_util.cc
@@ -17,6 +17,27 @@
 #include "node_geometry_util.hh"
 #include "node_util.h"
 
+namespace blender::nodes {
+
+void update_attribute_input_socket_availabilities(bNode &node,
+                                                  const StringRef name,
+                                                  const GeometryNodeAttributeInputMode mode)
+{
+  const GeometryNodeAttributeInputMode mode_ = (GeometryNodeAttributeInputMode)mode;
+  LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) {
+    if (name == socket->name) {
+      const bool is_available =
+          ((socket->type == SOCK_STRING && mode_ == GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE) ||
+           (socket->type == SOCK_FLOAT && mode_ == GEO_NODE_ATTRIBUTE_INPUT_FLOAT) ||
+           (socket->type == SOCK_VECTOR && mode_ == GEO_NODE_ATTRIBUTE_INPUT_VECTOR) ||
+           (socket->type == SOCK_RGBA && mode_ == GEO_NODE_ATTRIBUTE_INPUT_COLOR));
+      nodeSetSocketAvailability(socket, is_available);
+    }
+  }
+}
+
+}  // namespace blender::nodes
+
 bool geo_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree)
 {
   return STREQ(ntree->idname, "GeometryNodeTree");
diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh
index bb26763642b..ec389961615 100644
--- a/source/blender/nodes/geometry/node_geometry_util.hh
+++ b/source/blender/nodes/geometry/node_geometry_util.hh
@@ -37,3 +37,9 @@
 void geo_node_type_base(
     struct bNodeType *ntype, int type, const char *name, short nclass, short flag);
 bool geo_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree);
+
+namespace blender::nodes {
+void update_attribute_input_socket_availabilities(bNode &node,
+                                                  const StringRef name,
+                                                  const GeometryNodeAttributeInputMode mode);
+}
diff --git a/source/blender/nodes/intern/node_geometry_exec.cc b/source/blender/nodes/intern/node_geometry_exec.cc
index 50292cb8cfb..a6d9115f01f 100644
--- a/source/blender/nodes/intern/node_geometry_exec.cc
+++ b/source/blender/nodes/intern/node_geometry_exec.cc
@@ -19,6 +19,47 @@
 
 namespace blender::nodes {
 
+ReadAttributePtr GeoNodeExecParams::get_input_attribute(const StringRef name,
+                                                        const GeometryComponent &component,
+                                                        const AttributeDomain domain,
+                                                        const CustomDataType type,
+                                                        const void *default_value) const
+{
+  const bNodeSocket *found_socket = nullptr;
+  LISTBASE_FOREACH (const bNodeSocket *, socket, &node_.inputs) {
+    if ((socket->flag & SOCK_UNAVAIL) != 0) {
+      continue;
+    }
+    if (name == socket->name) {
+      found_socket = socket;
+      break;
+    }
+  }
+  BLI_assert(found_socket != nullptr);
+
+  if (found_socket->type == SOCK_STRING) {
+    const std::string name = this->get_input<std::string>(found_socket->identifier);
+    return component.attribute_get_for_read(name, domain, type, default_value);
+  }
+  if (found_socket->type == SOCK_FLOAT) {
+    const float value = this->get_input<float>(found_socket->identifier);
+    return component.attribute_get_constant_for_read_converted(
+        domain, CD_PROP_FLOAT, type, &value);
+  }
+  if (found_socket->type == SOCK_VECTOR) {
+    const float3 value = this->get_input<float3>(found_socket->identifier);
+    return component.attribute_get_constant_for_read_converted(
+        domain, CD_PROP_FLOAT3, type, &value);
+  }
+  if (found_socket->type == SOCK_RGBA) {
+    const Color4f value = this->get_input<Color4f>(found_socket->identifier);
+    return component.attribute_get_constant_for_read_converted(
+        domain, CD_PROP_COLOR, type, &value);
+  }
+  BLI_assert(false);
+  return component.attribute_get_constant_for_read(domain, type, default_value);
+}
+
 void GeoNodeExecParams::check_extract_input(StringRef identifier,
                                             const CPPType *requested_type) const
 {



More information about the Bf-blender-cvs mailing list