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-04-08 20:19:09 +0300
committerHans Goudey <h.goudey@me.com>2021-04-08 20:19:09 +0300
commit1ec9ac201652be6031379e39e98e7dd9dc4a2375 (patch)
tree880f6c342a8bb6f7dd4fdb7f5fbf611790c9fab1 /source/blender/blenkernel/intern/geometry_set_instances.cc
parentfd414b49068c011a1fd63a304ea95bbe420d6570 (diff)
Geometry Nodes: Support instances in attribute search
Previously only attributes of "real" geometry were displayed in attribute search. This commit adds code to look through attributes on instances and add those to the search drop-down too. This required implementing the same sort of recursive traversal as the realize instances code. The situation is a bit different though, this can return early and doesn't need to keep track of transforms. I added a limit so that it doesn't look through the attributes of too many instanced geometry sets. I think this is important, since this isn't a trivial operation and it could potentially happen for every node in a large node tree. Currently the limit is set at 8 geometry sets, which I expect will be enough, since the set of attributes is mostly not very unique anyway. Fixes T86282 Diffrential Revision: https://developer.blender.org/D10919
Diffstat (limited to 'source/blender/blenkernel/intern/geometry_set_instances.cc')
-rw-r--r--source/blender/blenkernel/intern/geometry_set_instances.cc116
1 files changed, 116 insertions, 0 deletions
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,