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.
This commit is contained in:
parent
25e151cc34
commit
4a5f36638b
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue