Attributes: Hide internal UI attributes and disallow procedural access

This commit hides "UI attributes" described in T97452 from the UI lists
in mesh, curve, and point cloud properties, and disallow accessing them
in geometry nodes.

Internal UI attributes like selection and hiding values should use the
attribute system for simplicity and performance, but we don't want to
expose those attributes in the attribute panel, which is meant for
regular user interaction. Procedural access may be misleading or cause
problems, as described in the design task above.

These attributes are added by two upcoming patches: D14934, D14685

Differential Revision: https://developer.blender.org/D15069
This commit is contained in:
Hans Goudey 2022-05-31 13:20:16 +02:00
parent 39c14f4e84
commit 4669178fc3
Notes: blender-bot 2023-02-14 09:33:11 +01:00
Referenced by commit 997ff54d30, Fix: UI: broken texpaintslot/color attributes/attributes name filtering
Referenced by issue #102878, Regression: UI texpaintslot/color attributes/attributes name filtering broken
13 changed files with 85 additions and 3 deletions

View File

@ -78,6 +78,16 @@ class CURVES_MT_add_attribute(Menu):
class CURVES_UL_attributes(UIList):
def filter_items(self, context, data, property):
attributes = getattr(data, property)
flags = []
indices = [i for i in range(len(attributes))]
for index, item in enumerate(attributes):
flags.append(self.bitflag_filter_item if item.is_internal else 0)
return flags, indices
def draw_item(self, _context, layout, _data, attribute, _icon, _active_data, _active_propname, _index):
data_type = attribute.bl_rna.properties['data_type'].enum_items[attribute.data_type]
domain = attribute.bl_rna.properties['domain'].enum_items[attribute.domain]

View File

@ -497,6 +497,16 @@ class MESH_UL_attributes(UIList):
'CORNER': "Face Corner",
}
def filter_items(self, context, data, property):
attributes = getattr(data, property)
flags = []
indices = [i for i in range(len(attributes))]
for index, item in enumerate(attributes):
flags.append(self.bitflag_filter_item if item.is_internal else 0)
return flags, indices
def draw_item(self, _context, layout, _data, attribute, _icon, _active_data, _active_propname, _index):
data_type = attribute.bl_rna.properties['data_type'].enum_items[attribute.data_type]
@ -576,7 +586,7 @@ class ColorAttributesListBase():
'CORNER': "Face Corner",
}
def filter_items(self, _context, data, property):
def filter_items(self, context, data, property):
attrs = getattr(data, property)
ret = []
idxs = []
@ -584,7 +594,8 @@ class ColorAttributesListBase():
for idx, item in enumerate(attrs):
skip = (
(item.domain not in {"POINT", "CORNER"}) or
(item.data_type not in {"FLOAT_COLOR", "BYTE_COLOR"})
(item.data_type not in {"FLOAT_COLOR", "BYTE_COLOR"}) or
(not item.is_internal)
)
ret.append(self.bitflag_filter_item if not skip else 0)
idxs.append(idx)

View File

@ -67,6 +67,16 @@ class POINTCLOUD_MT_add_attribute(Menu):
class POINTCLOUD_UL_attributes(UIList):
def filter_items(self, context, data, property):
attributes = getattr(data, property)
flags = []
indices = [i for i in range(len(attributes))]
for index, item in enumerate(attributes):
flags.append(self.bitflag_filter_item if item.is_internal else 0)
return flags, indices
def draw_item(self, _context, layout, _data, attribute, _icon, _active_data, _active_propname, _index):
data_type = attribute.bl_rna.properties['data_type'].enum_items[attribute.data_type]

View File

@ -49,6 +49,7 @@ typedef enum AttributeDomainMask {
/* Attributes. */
bool BKE_id_attributes_supported(struct ID *id);
bool BKE_attribute_allow_procedural_access(const char *attribute_name);
/**
* Create a new attribute layer.

View File

@ -77,6 +77,9 @@ class AttributeIDRef {
friend std::ostream &operator<<(std::ostream &stream, const AttributeIDRef &attribute_id);
};
bool allow_procedural_attribute_access(StringRef attribute_name);
extern const char *no_procedural_access_message;
} // namespace blender::bke
/**

View File

@ -23,6 +23,7 @@
#include "BLI_string_utils.h"
#include "BKE_attribute.h"
#include "BKE_attribute_access.hh"
#include "BKE_curves.h"
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
@ -116,6 +117,11 @@ bool BKE_id_attributes_supported(ID *id)
return false;
}
bool BKE_attribute_allow_procedural_access(const char *attribute_name)
{
return blender::bke::allow_procedural_attribute_access(attribute_name);
}
bool BKE_id_attribute_rename(ID *id,
CustomDataLayer *layer,
const char *new_name,

View File

@ -55,6 +55,14 @@ std::ostream &operator<<(std::ostream &stream, const AttributeIDRef &attribute_i
return stream;
}
const char *no_procedural_access_message =
"This attribute can not be accessed in a procedural context";
bool allow_procedural_attribute_access(StringRef attribute_name)
{
return !attribute_name.startswith(".selection");
}
static int attribute_data_type_complexity(const CustomDataType data_type)
{
switch (data_type) {

View File

@ -91,6 +91,9 @@ void attribute_search_add_items(StringRefNull str,
if (item->name == "normal" && item->domain == ATTR_DOMAIN_FACE) {
continue;
}
if (!bke::allow_procedural_attribute_access(item->name)) {
continue;
}
BLI_string_search_add(search, item->name.c_str(), (void *)item, 0);
}

View File

@ -81,6 +81,9 @@ void GeometryDataSource::foreach_default_column_ids(
if (attribute_id.is_anonymous()) {
return true;
}
if (!bke::allow_procedural_attribute_access(attribute_id.name())) {
return true;
}
SpreadsheetColumnID column_id;
column_id.name = (char *)attribute_id.name().data();
fn(column_id, false);

View File

@ -232,6 +232,12 @@ static int rna_Attribute_domain_get(PointerRNA *ptr)
return BKE_id_attribute_domain(ptr->owner_id, ptr->data);
}
static bool rna_Attribute_is_internal_get(PointerRNA *ptr)
{
const CustomDataLayer *layer = (const CustomDataLayer *)ptr->data;
return BKE_attribute_allow_procedural_access(layer->name);
}
static void rna_Attribute_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
ID *id = ptr->owner_id;
@ -930,6 +936,12 @@ static void rna_def_attribute(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Domain", "Domain of the Attribute");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "is_internal", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_Attribute_is_internal_get", NULL);
RNA_def_property_ui_text(
prop, "Is Internal", "The attribute is meant for internal use by Blender");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
/* types */
rna_def_attribute_float(brna);
rna_def_attribute_float_vector(brna);
@ -942,7 +954,7 @@ static void rna_def_attribute(BlenderRNA *brna)
rna_def_attribute_int8(brna);
}
/* Mesh/PointCloud/Hair.attributes */
/* Mesh/PointCloud/Curves.attributes */
static void rna_def_attribute_group(BlenderRNA *brna)
{
StructRNA *srna;

View File

@ -82,6 +82,11 @@ static void node_geo_exec(GeoNodeExecParams params)
params.set_default_remaining_outputs();
return;
}
if (!bke::allow_procedural_attribute_access(name)) {
params.error_message_add(NodeWarningType::Info, TIP_(bke::no_procedural_access_message));
params.set_default_remaining_outputs();
return;
}
params.used_named_attribute(name, NamedAttributeUsage::Read);

View File

@ -21,6 +21,11 @@ static void node_geo_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
return;
}
if (!bke::allow_procedural_attribute_access(name)) {
params.error_message_add(NodeWarningType::Info, TIP_(bke::no_procedural_access_message));
params.set_output("Geometry", std::move(geometry_set));
return;
}
std::atomic<bool> attribute_exists = false;
std::atomic<bool> cannot_delete = false;

View File

@ -131,6 +131,11 @@ static void node_geo_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
return;
}
if (!bke::allow_procedural_attribute_access(name)) {
params.error_message_add(NodeWarningType::Info, TIP_(bke::no_procedural_access_message));
params.set_output("Geometry", std::move(geometry_set));
return;
}
params.used_named_attribute(name, NamedAttributeUsage::Write);