diff options
-rw-r--r-- | source/blender/depsgraph/DEG_depsgraph_query.h | 10 | ||||
-rw-r--r-- | source/blender/depsgraph/intern/depsgraph_query_iter.cc | 225 |
2 files changed, 156 insertions, 79 deletions
diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h index 7eb5f1ccec1..f877e99b16b 100644 --- a/source/blender/depsgraph/DEG_depsgraph_query.h +++ b/source/blender/depsgraph/DEG_depsgraph_query.h @@ -145,6 +145,16 @@ typedef struct DEGObjectIterData { eEvaluationMode eval_mode; + /* **** Iteration over geometry components **** */ + + /* The object whose components we currently iterate over. + * This might point to #temp_dupli_object. */ + struct Object *geometry_component_owner; + /* Some identifier that is used to determine which geometry component should be returned next. */ + int geometry_component_id; + /* Temporary storage for an object that is created from a component. */ + struct Object temp_geometry_component_object; + /* **** Iteration over dupli-list. *** */ /* Object which created the dupli-list. */ diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index dd5c998466b..b92bf475f49 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -29,6 +29,7 @@ #include "MEM_guardedalloc.h" #include "BKE_duplilist.h" +#include "BKE_geometry_set.hh" #include "BKE_idprop.h" #include "BKE_layer.h" #include "BKE_node.h" @@ -121,9 +122,84 @@ bool deg_object_hide_original(eEvaluationMode eval_mode, Object *ob, DupliObject return false; } -bool deg_objects_dupli_iterator_next(BLI_Iterator *iter) +void deg_iterator_components_init(DEGObjectIterData *data, Object *object) +{ + data->geometry_component_owner = object; + data->geometry_component_id = 0; +} + +/* Returns false when iterator is exhausted. */ +bool deg_iterator_components_step(BLI_Iterator *iter) { DEGObjectIterData *data = (DEGObjectIterData *)iter->data; + if (data->geometry_component_owner == nullptr) { + return false; + } + + if (data->geometry_component_owner->type != OB_POINTCLOUD) { + /* Only point clouds support multiple geometry components currently. */ + iter->current = data->geometry_component_owner; + data->geometry_component_owner = nullptr; + return true; + } + + GeometrySet *geometry_set = data->geometry_component_owner->runtime.geometry_set_eval; + if (geometry_set == nullptr) { + data->geometry_component_owner = nullptr; + return false; + } + + if (data->geometry_component_id == 0) { + data->geometry_component_id++; + + /* The mesh component. */ + const Mesh *mesh = geometry_set->get_mesh_for_read(); + if (mesh != nullptr) { + Object *temp_object = &data->temp_geometry_component_object; + *temp_object = *data->geometry_component_owner; + temp_object->type = OB_MESH; + temp_object->data = (void *)mesh; + temp_object->runtime.select_id = data->geometry_component_owner->runtime.select_id; + iter->current = temp_object; + return true; + } + } + if (data->geometry_component_id == 1) { + data->geometry_component_id++; + + /* The pointcloud component. */ + const PointCloud *pointcloud = geometry_set->get_pointcloud_for_read(); + if (pointcloud != nullptr) { + Object *temp_object = &data->temp_geometry_component_object; + *temp_object = *data->geometry_component_owner; + temp_object->type = OB_POINTCLOUD; + temp_object->data = (void *)pointcloud; + temp_object->runtime.select_id = data->geometry_component_owner->runtime.select_id; + iter->current = temp_object; + return true; + } + } + data->geometry_component_owner = nullptr; + return false; +} + +void deg_iterator_duplis_init(DEGObjectIterData *data, Object *object) +{ + if ((data->flag & DEG_ITER_OBJECT_FLAG_DUPLI) && + ((object->transflag & OB_DUPLI) || object->runtime.geometry_set_eval != nullptr)) { + data->dupli_parent = object; + data->dupli_list = object_duplilist(data->graph, data->scene, object); + data->dupli_object_next = (DupliObject *)data->dupli_list->first; + } +} + +/* Returns false when iterator is exhausted. */ +bool deg_iterator_duplis_step(DEGObjectIterData *data) +{ + if (data->dupli_list == nullptr) { + return false; + } + while (data->dupli_object_next != nullptr) { DupliObject *dob = data->dupli_object_next; Object *obd = dob->ob; @@ -171,73 +247,81 @@ bool deg_objects_dupli_iterator_next(BLI_Iterator *iter) copy_m4_m4(data->temp_dupli_object.obmat, dob->mat); invert_m4_m4(data->temp_dupli_object.imat, data->temp_dupli_object.obmat); - iter->current = &data->temp_dupli_object; + deg_iterator_components_init(data, &data->temp_dupli_object); BLI_assert(deg::deg_validate_copy_on_write_datablock(&data->temp_dupli_object.id)); return true; } + verify_id_properties_freed(data); + free_object_duplilist(data->dupli_list); + data->dupli_parent = nullptr; + data->dupli_list = nullptr; + data->dupli_object_next = nullptr; + data->dupli_object_current = nullptr; + deg_invalidate_iterator_work_data(data); return false; } -void deg_iterator_objects_step(BLI_Iterator *iter, deg::IDNode *id_node) +/* Returns false when iterator is exhausted. */ +bool deg_iterator_objects_step(DEGObjectIterData *data) { - /* Set it early in case we need to exit and we are running from within a loop. */ - iter->skip = true; + deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(data->graph); - if (!id_node->is_directly_visible) { - return; - } + for (; data->id_node_index < data->num_id_nodes; data->id_node_index++) { + deg::IDNode *id_node = deg_graph->id_nodes[data->id_node_index]; - DEGObjectIterData *data = (DEGObjectIterData *)iter->data; - const ID_Type id_type = GS(id_node->id_orig->name); + if (!id_node->is_directly_visible) { + continue; + } - if (id_type != ID_OB) { - return; - } + const ID_Type id_type = GS(id_node->id_orig->name); - switch (id_node->linked_state) { - case deg::DEG_ID_LINKED_DIRECTLY: - if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY) == 0) { - return; - } - break; - case deg::DEG_ID_LINKED_VIA_SET: - if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET) == 0) { - return; - } - break; - case deg::DEG_ID_LINKED_INDIRECTLY: - if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY) == 0) { - return; - } - break; - } + if (id_type != ID_OB) { + continue; + } - Object *object = (Object *)id_node->id_cow; - BLI_assert(deg::deg_validate_copy_on_write_datablock(&object->id)); + switch (id_node->linked_state) { + case deg::DEG_ID_LINKED_DIRECTLY: + if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY) == 0) { + continue; + } + break; + case deg::DEG_ID_LINKED_VIA_SET: + if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET) == 0) { + continue; + } + break; + case deg::DEG_ID_LINKED_INDIRECTLY: + if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY) == 0) { + continue; + } + break; + } - int ob_visibility = OB_VISIBLE_ALL; - if (data->flag & DEG_ITER_OBJECT_FLAG_VISIBLE) { - ob_visibility = BKE_object_visibility(object, data->eval_mode); + Object *object = (Object *)id_node->id_cow; + BLI_assert(deg::deg_validate_copy_on_write_datablock(&object->id)); - if (object->type != OB_MBALL && deg_object_hide_original(data->eval_mode, object, nullptr)) { - return; + int ob_visibility = OB_VISIBLE_ALL; + if (data->flag & DEG_ITER_OBJECT_FLAG_VISIBLE) { + ob_visibility = BKE_object_visibility(object, data->eval_mode); + + if (object->type != OB_MBALL && deg_object_hide_original(data->eval_mode, object, nullptr)) { + continue; + } } - } - object->runtime.select_id = DEG_get_original_object(object)->runtime.select_id; - if (ob_visibility & OB_VISIBLE_INSTANCES) { - if ((data->flag & DEG_ITER_OBJECT_FLAG_DUPLI) && (object->transflag & OB_DUPLI)) { - data->dupli_parent = object; - data->dupli_list = object_duplilist(data->graph, data->scene, object); - data->dupli_object_next = (DupliObject *)data->dupli_list->first; + object->runtime.select_id = DEG_get_original_object(object)->runtime.select_id; + if (ob_visibility & OB_VISIBLE_INSTANCES) { + deg_iterator_duplis_init(data, object); } - } - if (ob_visibility & (OB_VISIBLE_SELF | OB_VISIBLE_PARTICLES)) { - iter->current = object; - iter->skip = false; + if (ob_visibility & (OB_VISIBLE_SELF | OB_VISIBLE_PARTICLES)) { + deg_iterator_components_init(data, object); + } + data->id_node_index++; + return true; } + return false; } } // namespace @@ -263,46 +347,29 @@ void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data) data->id_node_index = 0; data->num_id_nodes = num_id_nodes; data->eval_mode = DEG_get_mode(depsgraph); + data->geometry_component_id = 0; + data->geometry_component_owner = nullptr; deg_invalidate_iterator_work_data(data); - deg::IDNode *id_node = deg_graph->id_nodes[data->id_node_index]; - deg_iterator_objects_step(iter, id_node); - - if (iter->skip) { - DEG_iterator_objects_next(iter); - } + DEG_iterator_objects_next(iter); } void DEG_iterator_objects_next(BLI_Iterator *iter) { DEGObjectIterData *data = (DEGObjectIterData *)iter->data; - Depsgraph *depsgraph = data->graph; - deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph); - do { - iter->skip = false; - if (data->dupli_list) { - if (deg_objects_dupli_iterator_next(iter)) { - return; - } - - verify_id_properties_freed(data); - free_object_duplilist(data->dupli_list); - data->dupli_parent = nullptr; - data->dupli_list = nullptr; - data->dupli_object_next = nullptr; - data->dupli_object_current = nullptr; - deg_invalidate_iterator_work_data(data); - } - - ++data->id_node_index; - if (data->id_node_index == data->num_id_nodes) { - iter->valid = false; + while (true) { + if (deg_iterator_components_step(iter)) { return; } - - deg::IDNode *id_node = deg_graph->id_nodes[data->id_node_index]; - deg_iterator_objects_step(iter, id_node); - } while (iter->skip); + if (deg_iterator_duplis_step(data)) { + continue; + } + if (deg_iterator_objects_step(data)) { + continue; + } + iter->valid = false; + break; + } } void DEG_iterator_objects_end(BLI_Iterator *iter) |