Geometry Nodes: move some attribute utilities to blenkernel
I need to access these utilities from modifier code as well. Therefore, they should not live in the nodes module.
This commit is contained in:
@@ -33,6 +33,8 @@ using fn::CPPType;
|
||||
|
||||
const CPPType *custom_data_type_to_cpp_type(const CustomDataType type);
|
||||
CustomDataType cpp_type_to_custom_data_type(const CPPType &type);
|
||||
CustomDataType attribute_data_type_highest_complexity(Span<CustomDataType> data_types);
|
||||
AttributeDomain attribute_domain_highest_priority(Span<AttributeDomain> domains);
|
||||
|
||||
/**
|
||||
* This class offers an indirection for reading an attribute.
|
||||
|
||||
@@ -508,6 +508,96 @@ CustomDataType cpp_type_to_custom_data_type(const blender::fn::CPPType &type)
|
||||
return static_cast<CustomDataType>(-1);
|
||||
}
|
||||
|
||||
static int attribute_data_type_complexity(const CustomDataType data_type)
|
||||
{
|
||||
switch (data_type) {
|
||||
case CD_PROP_BOOL:
|
||||
return 0;
|
||||
case CD_PROP_INT32:
|
||||
return 1;
|
||||
case CD_PROP_FLOAT:
|
||||
return 2;
|
||||
case CD_PROP_FLOAT2:
|
||||
return 3;
|
||||
case CD_PROP_FLOAT3:
|
||||
return 4;
|
||||
case CD_PROP_COLOR:
|
||||
return 5;
|
||||
#if 0 /* These attribute types are not supported yet. */
|
||||
case CD_MLOOPCOL:
|
||||
return 3;
|
||||
case CD_PROP_STRING:
|
||||
return 6;
|
||||
#endif
|
||||
default:
|
||||
/* Only accept "generic" custom data types used by the attribute system. */
|
||||
BLI_assert(false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
CustomDataType attribute_data_type_highest_complexity(Span<CustomDataType> data_types)
|
||||
{
|
||||
int highest_complexity = INT_MIN;
|
||||
CustomDataType most_complex_type = CD_PROP_COLOR;
|
||||
|
||||
for (const CustomDataType data_type : data_types) {
|
||||
const int complexity = attribute_data_type_complexity(data_type);
|
||||
if (complexity > highest_complexity) {
|
||||
highest_complexity = complexity;
|
||||
most_complex_type = data_type;
|
||||
}
|
||||
}
|
||||
|
||||
return most_complex_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* \note Generally the order should mirror the order of the domains
|
||||
* established in each component's ComponentAttributeProviders.
|
||||
*/
|
||||
static int attribute_domain_priority(const AttributeDomain domain)
|
||||
{
|
||||
switch (domain) {
|
||||
#if 0
|
||||
case ATTR_DOMAIN_CURVE:
|
||||
return 0;
|
||||
#endif
|
||||
case ATTR_DOMAIN_POLYGON:
|
||||
return 1;
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return 2;
|
||||
case ATTR_DOMAIN_POINT:
|
||||
return 3;
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
return 4;
|
||||
default:
|
||||
/* Domain not supported in nodes yet. */
|
||||
BLI_assert(false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Domains with a higher "information density" have a higher priority, in order
|
||||
* to choose a domain that will not lose data through domain conversion.
|
||||
*/
|
||||
AttributeDomain attribute_domain_highest_priority(Span<AttributeDomain> domains)
|
||||
{
|
||||
int highest_priority = INT_MIN;
|
||||
AttributeDomain highest_priority_domain = ATTR_DOMAIN_CORNER;
|
||||
|
||||
for (const AttributeDomain domain : domains) {
|
||||
const int priority = attribute_domain_priority(domain);
|
||||
if (priority > highest_priority) {
|
||||
highest_priority = priority;
|
||||
highest_priority_domain = domain;
|
||||
}
|
||||
}
|
||||
|
||||
return highest_priority_domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* A #BuiltinAttributeProvider is responsible for exactly one attribute on a geometry component.
|
||||
* The attribute is identified by its name and has a fixed domain and type. Builtin attributes do
|
||||
|
||||
@@ -55,7 +55,8 @@ void gather_attribute_info(Map<std::string, AttributeInfo> &attributes,
|
||||
};
|
||||
auto modify_info = [&, data_type, domain](AttributeInfo *info) {
|
||||
info->domain = domain; /* TODO: Use highest priority domain. */
|
||||
info->data_type = attribute_data_type_highest_complexity({info->data_type, data_type});
|
||||
info->data_type = bke::attribute_data_type_highest_complexity(
|
||||
{info->data_type, data_type});
|
||||
};
|
||||
|
||||
attributes.add_or_modify(name, add_info, modify_info);
|
||||
@@ -294,96 +295,6 @@ void update_attribute_input_socket_availabilities(bNode &node,
|
||||
}
|
||||
}
|
||||
|
||||
static int attribute_data_type_complexity(const CustomDataType data_type)
|
||||
{
|
||||
switch (data_type) {
|
||||
case CD_PROP_BOOL:
|
||||
return 0;
|
||||
case CD_PROP_INT32:
|
||||
return 1;
|
||||
case CD_PROP_FLOAT:
|
||||
return 2;
|
||||
case CD_PROP_FLOAT2:
|
||||
return 3;
|
||||
case CD_PROP_FLOAT3:
|
||||
return 4;
|
||||
case CD_PROP_COLOR:
|
||||
return 5;
|
||||
#if 0 /* These attribute types are not supported yet. */
|
||||
case CD_MLOOPCOL:
|
||||
return 3;
|
||||
case CD_PROP_STRING:
|
||||
return 6;
|
||||
#endif
|
||||
default:
|
||||
/* Only accept "generic" custom data types used by the attribute system. */
|
||||
BLI_assert(false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
CustomDataType attribute_data_type_highest_complexity(Span<CustomDataType> data_types)
|
||||
{
|
||||
int highest_complexity = INT_MIN;
|
||||
CustomDataType most_complex_type = CD_PROP_COLOR;
|
||||
|
||||
for (const CustomDataType data_type : data_types) {
|
||||
const int complexity = attribute_data_type_complexity(data_type);
|
||||
if (complexity > highest_complexity) {
|
||||
highest_complexity = complexity;
|
||||
most_complex_type = data_type;
|
||||
}
|
||||
}
|
||||
|
||||
return most_complex_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* \note Generally the order should mirror the order of the domains
|
||||
* established in each component's ComponentAttributeProviders.
|
||||
*/
|
||||
static int attribute_domain_priority(const AttributeDomain domain)
|
||||
{
|
||||
switch (domain) {
|
||||
#if 0
|
||||
case ATTR_DOMAIN_CURVE:
|
||||
return 0;
|
||||
#endif
|
||||
case ATTR_DOMAIN_POLYGON:
|
||||
return 1;
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return 2;
|
||||
case ATTR_DOMAIN_POINT:
|
||||
return 3;
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
return 4;
|
||||
default:
|
||||
/* Domain not supported in nodes yet. */
|
||||
BLI_assert(false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Domains with a higher "information density" have a higher priority, in order
|
||||
* to choose a domain that will not lose data through domain conversion.
|
||||
*/
|
||||
AttributeDomain attribute_domain_highest_priority(Span<AttributeDomain> domains)
|
||||
{
|
||||
int highest_priority = INT_MIN;
|
||||
AttributeDomain highest_priority_domain = ATTR_DOMAIN_CORNER;
|
||||
|
||||
for (const AttributeDomain domain : domains) {
|
||||
const int priority = attribute_domain_priority(domain);
|
||||
if (priority > highest_priority) {
|
||||
highest_priority = priority;
|
||||
highest_priority_domain = domain;
|
||||
}
|
||||
}
|
||||
|
||||
return highest_priority_domain;
|
||||
}
|
||||
|
||||
} // namespace blender::nodes
|
||||
|
||||
bool geo_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree)
|
||||
|
||||
@@ -44,9 +44,6 @@ void update_attribute_input_socket_availabilities(bNode &node,
|
||||
const GeometryNodeAttributeInputMode mode,
|
||||
const bool name_is_available = true);
|
||||
|
||||
CustomDataType attribute_data_type_highest_complexity(Span<CustomDataType>);
|
||||
AttributeDomain attribute_domain_highest_priority(Span<AttributeDomain> domains);
|
||||
|
||||
Array<uint32_t> get_geometry_element_ids_as_uints(const GeometryComponent &component,
|
||||
const AttributeDomain domain);
|
||||
|
||||
|
||||
@@ -230,7 +230,7 @@ static CustomDataType get_data_type(GeometryComponent &component,
|
||||
if (operation_tests_equality(node_storage)) {
|
||||
/* Convert the input attributes to the same data type for the equality tests. Use the higher
|
||||
* complexity attribute type, otherwise information necessary to the comparison may be lost. */
|
||||
return attribute_data_type_highest_complexity({
|
||||
return bke::attribute_data_type_highest_complexity({
|
||||
params.get_input_attribute_data_type("A", component, CD_PROP_FLOAT),
|
||||
params.get_input_attribute_data_type("B", component, CD_PROP_FLOAT),
|
||||
});
|
||||
|
||||
@@ -148,7 +148,7 @@ static void attribute_mix_calc(GeometryComponent &component, const GeoNodeExecPa
|
||||
/* Use the highest complexity data type among the inputs and outputs, that way the node will
|
||||
* never "remove information". Use CD_PROP_BOOL as the lowest complexity data type, but in any
|
||||
* real situation it won't be returned. */
|
||||
const CustomDataType result_type = attribute_data_type_highest_complexity({
|
||||
const CustomDataType result_type = bke::attribute_data_type_highest_complexity({
|
||||
params.get_input_attribute_data_type("A", component, CD_PROP_BOOL),
|
||||
params.get_input_attribute_data_type("B", component, CD_PROP_BOOL),
|
||||
params.get_input_attribute_data_type("Result", component, CD_PROP_BOOL),
|
||||
|
||||
@@ -90,7 +90,7 @@ static AttributeDomain get_result_domain(const GeometryComponent &component,
|
||||
output_domains.append(attribute_z->domain());
|
||||
}
|
||||
if (output_domains.size() > 0) {
|
||||
return attribute_domain_highest_priority(output_domains);
|
||||
return bke::attribute_domain_highest_priority(output_domains);
|
||||
}
|
||||
|
||||
/* Otherwise use the domain of the input attribute, or the default. */
|
||||
|
||||
@@ -156,8 +156,8 @@ static void determine_final_data_type_and_domain(Span<const GeometryComponent *>
|
||||
}
|
||||
}
|
||||
|
||||
*r_type = attribute_data_type_highest_complexity(data_types);
|
||||
*r_domain = attribute_domain_highest_priority(domains);
|
||||
*r_type = bke::attribute_data_type_highest_complexity(data_types);
|
||||
*r_domain = bke::attribute_domain_highest_priority(domains);
|
||||
}
|
||||
|
||||
static void fill_new_attribute(Span<const GeometryComponent *> src_components,
|
||||
|
||||
@@ -134,7 +134,7 @@ AttributeDomain GeoNodeExecParams::get_highest_priority_input_domain(
|
||||
}
|
||||
|
||||
if (input_domains.size() > 0) {
|
||||
return attribute_domain_highest_priority(input_domains);
|
||||
return bke::attribute_domain_highest_priority(input_domains);
|
||||
}
|
||||
|
||||
return default_domain;
|
||||
|
||||
Reference in New Issue
Block a user