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:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh2
-rw-r--r--source/blender/blenkernel/BKE_geometry_set_instances.hh4
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc14
-rw-r--r--source/blender/blenkernel/intern/geometry_set_instances.cc116
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc28
5 files changed, 145 insertions, 19 deletions
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 2ce8ce5749f..d94b2e7902b 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -186,7 +186,7 @@ class GeometryComponent {
const CustomDataType data_type);
blender::Set<std::string> attribute_names() const;
- void attribute_foreach(const AttributeForeachCallback callback) const;
+ bool attribute_foreach(const AttributeForeachCallback callback) const;
virtual bool is_empty() const;
diff --git a/source/blender/blenkernel/BKE_geometry_set_instances.hh b/source/blender/blenkernel/BKE_geometry_set_instances.hh
index c0d9c3f74ec..25876296a47 100644
--- a/source/blender/blenkernel/BKE_geometry_set_instances.hh
+++ b/source/blender/blenkernel/BKE_geometry_set_instances.hh
@@ -39,6 +39,10 @@ struct GeometryInstanceGroup {
Vector<float4x4> transforms;
};
+void geometry_set_instances_attribute_foreach(const GeometrySet &geometry_set,
+ const AttributeForeachCallback callback,
+ const int limit);
+
void geometry_set_gather_instances(const GeometrySet &geometry_set,
Vector<GeometryInstanceGroup> &r_instance_groups);
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index 52f89ca302b..5bd3b990a63 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -822,12 +822,16 @@ Set<std::string> GeometryComponent::attribute_names() const
return attributes;
}
-void GeometryComponent::attribute_foreach(const AttributeForeachCallback callback) const
+/**
+ * \return False if the callback explicitly returned false at any point, otherwise true,
+ * meaning the callback made it all the way through.
+ */
+bool GeometryComponent::attribute_foreach(const AttributeForeachCallback callback) const
{
using namespace blender::bke;
const ComponentAttributeProviders *providers = this->get_attribute_providers();
if (providers == nullptr) {
- return;
+ return true;
}
/* Keep track handled attribute names to make sure that we do not return the same name twice. */
@@ -838,7 +842,7 @@ void GeometryComponent::attribute_foreach(const AttributeForeachCallback callbac
if (provider->exists(*this)) {
AttributeMetaData meta_data{provider->domain(), provider->data_type()};
if (!callback(provider->name(), meta_data)) {
- return;
+ return false;
}
handled_attribute_names.add_new(provider->name());
}
@@ -852,9 +856,11 @@ void GeometryComponent::attribute_foreach(const AttributeForeachCallback callbac
return true;
});
if (!continue_loop) {
- return;
+ return false;
}
}
+
+ return true;
}
bool GeometryComponent::attribute_exists(const blender::StringRef attribute_name) const
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index 1a45eac8cab..baeed4fc3bc 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -162,6 +162,122 @@ void geometry_set_gather_instances(const GeometrySet &geometry_set,
geometry_set_collect_recursive(geometry_set, unit_transform, r_instance_groups);
}
+static bool collection_instance_attribute_foreach(const Collection &collection,
+ const AttributeForeachCallback callback,
+ const int limit,
+ int &count);
+
+static bool instances_attribute_foreach_recursive(const GeometrySet &geometry_set,
+ const AttributeForeachCallback callback,
+ const int limit,
+ int &count);
+
+static bool object_instance_attribute_foreach(const Object &object,
+ const AttributeForeachCallback callback,
+ const int limit,
+ int &count)
+{
+ GeometrySet instance_geometry_set = object_get_geometry_set_for_read(object);
+ if (!instances_attribute_foreach_recursive(instance_geometry_set, callback, limit, count)) {
+ return false;
+ }
+
+ if (object.type == OB_EMPTY) {
+ const Collection *collection_instance = object.instance_collection;
+ if (collection_instance != nullptr) {
+ if (!collection_instance_attribute_foreach(*collection_instance, callback, limit, count)) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+static bool collection_instance_attribute_foreach(const Collection &collection,
+ const AttributeForeachCallback callback,
+ const int limit,
+ int &count)
+{
+ LISTBASE_FOREACH (const CollectionObject *, collection_object, &collection.gobject) {
+ BLI_assert(collection_object->ob != nullptr);
+ const Object &object = *collection_object->ob;
+ if (!object_instance_attribute_foreach(object, callback, limit, count)) {
+ return false;
+ }
+ }
+ LISTBASE_FOREACH (const CollectionChild *, collection_child, &collection.children) {
+ BLI_assert(collection_child->collection != nullptr);
+ const Collection &collection = *collection_child->collection;
+ if (!collection_instance_attribute_foreach(collection, callback, limit, count)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+ * \return True if the recursive iteration should continue, false if the limit is reached or the
+ * callback has returned false indicating it should stop.
+ */
+static bool instances_attribute_foreach_recursive(const GeometrySet &geometry_set,
+ const AttributeForeachCallback callback,
+ const int limit,
+ int &count)
+{
+ for (const GeometryComponent *component : geometry_set.get_components_for_read()) {
+ if (!component->attribute_foreach(callback)) {
+ return false;
+ }
+ }
+
+ /* Now that this this geometry set is visited, increase the count and check with the limit. */
+ if (limit > 0 && count++ > limit) {
+ return false;
+ }
+
+ const InstancesComponent *instances_component =
+ geometry_set.get_component_for_read<InstancesComponent>();
+ if (instances_component == nullptr) {
+ return true;
+ }
+
+ for (const InstancedData &data : instances_component->instanced_data()) {
+ if (data.type == INSTANCE_DATA_TYPE_OBJECT) {
+ BLI_assert(data.data.object != nullptr);
+ const Object &object = *data.data.object;
+ if (!object_instance_attribute_foreach(object, callback, limit, count)) {
+ return false;
+ }
+ }
+ else if (data.type == INSTANCE_DATA_TYPE_COLLECTION) {
+ BLI_assert(data.data.collection != nullptr);
+ const Collection &collection = *data.data.collection;
+ if (!collection_instance_attribute_foreach(collection, callback, limit, count)) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Call the callback on all of this geometry set's components, including geometry sets from
+ * instances and recursive instances. This is necessary to access available attributes without
+ * making all of the set's geometry real.
+ *
+ * \param limit: The total number of geometry sets to visit before returning early. This is used
+ * to avoid looking through too many geometry sets recursively, as an explicit tradeoff in favor
+ * of performance at the cost of visiting every unique attribute.
+ */
+void geometry_set_instances_attribute_foreach(const GeometrySet &geometry_set,
+ const AttributeForeachCallback callback,
+ const int limit)
+{
+ int count = 0;
+ instances_attribute_foreach_recursive(geometry_set, callback, limit, count);
+}
+
void geometry_set_gather_instances_attribute_info(Span<GeometryInstanceGroup> set_groups,
Span<GeometryComponentType> component_types,
const Set<std::string> &ignored_attributes,
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index c7d822e5418..7a2f8640202 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -47,6 +47,7 @@
#include "DNA_windowmanager_types.h"
#include "BKE_customdata.h"
+#include "BKE_geometry_set_instances.hh"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_lib_query.h"
@@ -489,20 +490,19 @@ class GeometryNodesEvaluator {
const NodeTreeEvaluationContext context(*self_object_, *modifier_);
const GeometrySet &geometry_set = params.get_input<GeometrySet>(socket_ref->identifier());
- const Vector<const GeometryComponent *> components = geometry_set.get_components_for_read();
-
- for (const GeometryComponent *component : components) {
- component->attribute_foreach(
- [&](StringRefNull attribute_name, const AttributeMetaData &meta_data) {
- BKE_nodetree_attribute_hint_add(*btree_original,
- context,
- *node->bnode(),
- attribute_name,
- meta_data.domain,
- meta_data.data_type);
- return true;
- });
- }
+
+ blender::bke::geometry_set_instances_attribute_foreach(
+ geometry_set,
+ [&](StringRefNull attribute_name, const AttributeMetaData &meta_data) {
+ BKE_nodetree_attribute_hint_add(*btree_original,
+ context,
+ *node->bnode(),
+ attribute_name,
+ meta_data.domain,
+ meta_data.data_type);
+ return true;
+ },
+ 8);
}
}