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-10-20 18:54:54 +0300
committerHans Goudey <h.goudey@me.com>2021-10-20 18:54:54 +0300
commit40c3b8836b7a36303ea9c78b0932758cbf277f93 (patch)
tree84cf99f5f726384def64e79333b7566e36ff1156 /source/blender/blenkernel/intern/attribute_access.cc
parent1a96045eec96e0c6f52ded6fd40040c4b88524d9 (diff)
Geometry Nodes: Make Random ID a builtin attribute, remove sockets
In order to address feedback that the "Stable ID" was not easy enough to use, remove the "Stable ID" output from the distribution node and the input from the instance on points node. Instead, the nodes write or read a builtin named attribute called `id`. In the future we may add more attributes like `edge_id` and `face_id`. The downside is that more behavior is invisible, which is les expected now that most attributes are passed around with node links. This behavior will have to be explained in the manual. The random value node's "ID" input that had an implicit index input is converted to a special implicit input that uses the `id` attribute if possible, but otherwise defaults to the index. There is no way to tell in the UI which it uses, except by knowing that rule and checking in the spreadsheet for the id attribute. Because it isn't always possible to create stable randomness, this attribute does not always exist, and it will be possible to remove it when we have the attribute remove node back, to improve performance. Differential Revision: https://developer.blender.org/D12903
Diffstat (limited to 'source/blender/blenkernel/intern/attribute_access.cc')
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc114
1 files changed, 102 insertions, 12 deletions
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index d0510e0008e..930cabafb00 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -345,11 +345,18 @@ GVArrayPtr BuiltinCustomDataLayerProvider::try_get_for_read(
return {};
}
- const int domain_size = component.attribute_domain_size(domain_);
- const void *data = CustomData_get_layer(custom_data, stored_type_);
+ const void *data;
+ if (stored_as_named_attribute_) {
+ data = CustomData_get_layer_named(custom_data, stored_type_, name_.c_str());
+ }
+ else {
+ data = CustomData_get_layer(custom_data, stored_type_);
+ }
if (data == nullptr) {
return {};
}
+
+ const int domain_size = component.attribute_domain_size(domain_);
return as_read_attribute_(data, domain_size);
}
@@ -368,11 +375,21 @@ GVMutableArrayPtr BuiltinCustomDataLayerProvider::try_get_for_write(
if (data == nullptr) {
return {};
}
- void *new_data = CustomData_duplicate_referenced_layer(custom_data, stored_type_, domain_size);
+
+ void *new_data;
+ if (stored_as_named_attribute_) {
+ new_data = CustomData_duplicate_referenced_layer_named(
+ custom_data, stored_type_, name_.c_str(), domain_size);
+ }
+ else {
+ new_data = CustomData_duplicate_referenced_layer(custom_data, stored_type_, domain_size);
+ }
+
if (data != new_data) {
custom_data_access_.update_custom_data_pointers(component);
data = new_data;
}
+
if (update_on_write_ != nullptr) {
update_on_write_(component);
}
@@ -390,7 +407,19 @@ bool BuiltinCustomDataLayerProvider::try_delete(GeometryComponent &component) co
}
const int domain_size = component.attribute_domain_size(domain_);
- const int layer_index = CustomData_get_layer_index(custom_data, stored_type_);
+ int layer_index;
+ if (stored_as_named_attribute_) {
+ for (const int i : IndexRange(custom_data->totlayer)) {
+ if (custom_data_layer_matches_attribute_id(custom_data->layers[i], name_)) {
+ layer_index = i;
+ break;
+ }
+ }
+ }
+ else {
+ layer_index = CustomData_get_layer_index(custom_data, stored_type_);
+ }
+
const bool delete_success = CustomData_free_layer(
custom_data, stored_type_, domain_size, layer_index);
if (delete_success) {
@@ -409,14 +438,25 @@ bool BuiltinCustomDataLayerProvider::try_create(GeometryComponent &component,
if (custom_data == nullptr) {
return false;
}
- if (CustomData_get_layer(custom_data, stored_type_) != nullptr) {
- /* Exists already. */
- return false;
- }
const int domain_size = component.attribute_domain_size(domain_);
- const bool success = add_builtin_type_custom_data_layer_from_init(
- *custom_data, stored_type_, domain_size, initializer);
+ bool success;
+ if (stored_as_named_attribute_) {
+ if (CustomData_get_layer_named(custom_data, data_type_, name_.c_str())) {
+ /* Exists already. */
+ return false;
+ }
+ success = add_custom_data_layer_from_attribute_init(
+ name_, *custom_data, stored_type_, domain_size, initializer);
+ }
+ else {
+ if (CustomData_get_layer(custom_data, stored_type_) != nullptr) {
+ /* Exists already. */
+ return false;
+ }
+ success = add_builtin_type_custom_data_layer_from_init(
+ *custom_data, stored_type_, domain_size, initializer);
+ }
if (success) {
custom_data_access_.update_custom_data_pointers(component);
}
@@ -429,8 +469,10 @@ bool BuiltinCustomDataLayerProvider::exists(const GeometryComponent &component)
if (custom_data == nullptr) {
return false;
}
- const void *data = CustomData_get_layer(custom_data, stored_type_);
- return data != nullptr;
+ if (stored_as_named_attribute_) {
+ return CustomData_get_layer_named(custom_data, stored_type_, name_.c_str()) != nullptr;
+ }
+ return CustomData_get_layer(custom_data, stored_type_) != nullptr;
}
ReadAttributeLookup CustomDataAttributeProvider::try_get_for_read(
@@ -1353,6 +1395,54 @@ bool AttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
return false;
}
+static StringRef get_random_id_attribute_name(const AttributeDomain domain)
+{
+ switch (domain) {
+ case ATTR_DOMAIN_POINT:
+ return "id";
+ default:
+ return "";
+ }
+}
+
+const GVArray *IDAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
+ IndexMask mask,
+ ResourceScope &scope) const
+{
+ if (const GeometryComponentFieldContext *geometry_context =
+ dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
+ const GeometryComponent &component = geometry_context->geometry_component();
+ const AttributeDomain domain = geometry_context->domain();
+ const StringRef name = get_random_id_attribute_name(domain);
+ GVArrayPtr attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32);
+ if (attribute) {
+ BLI_assert(attribute->size() == component.attribute_domain_size(domain));
+ return scope.add(std::move(attribute));
+ }
+
+ /* Use the index as the fallback if no random ID attribute exists. */
+ return fn::IndexFieldInput::get_index_varray(mask, scope);
+ }
+ return nullptr;
+}
+
+std::string IDAttributeFieldInput::socket_inspection_name() const
+{
+ return TIP_("ID / Index");
+}
+
+uint64_t IDAttributeFieldInput::hash() const
+{
+ /* All random ID attribute inputs are the same within the same evaluation context. */
+ return 92386459827;
+}
+
+bool IDAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
+{
+ /* All random ID attribute inputs are the same within the same evaluation context. */
+ return dynamic_cast<const IDAttributeFieldInput *>(&other) != nullptr;
+}
+
const GVArray *AnonymousAttributeFieldInput::get_varray_for_context(
const fn::FieldContext &context, IndexMask UNUSED(mask), ResourceScope &scope) const
{