diff --git a/source/blender/blenkernel/BKE_duplilist.hh b/source/blender/blenkernel/BKE_duplilist.hh index 9c11c02132c..fd2d9cd666a 100644 --- a/source/blender/blenkernel/BKE_duplilist.hh +++ b/source/blender/blenkernel/BKE_duplilist.hh @@ -26,7 +26,10 @@ struct ViewerPath; /** * \return a #ListBase of #DupliObject. */ -ListBase *object_duplilist(Depsgraph *depsgraph, Scene *sce, Object *ob); +ListBase *object_duplilist(Depsgraph *depsgraph, + Scene *sce, + Object *ob, + blender::Set *include_objects = nullptr); /** * \return a #ListBase of #DupliObject for the preview geometry referenced by the #ViewerPath. */ diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index 9174284e24c..0e0e2f6bade 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -25,6 +25,7 @@ #include "BLI_math_rotation.h" #include "BLI_math_vector.hh" #include "BLI_rand.h" +#include "BLI_set.hh" #include "BLI_span.hh" #include "BLI_string_ref.hh" #include "BLI_vector.hh" @@ -71,6 +72,7 @@ using blender::Array; using blender::float2; using blender::float3; using blender::float4x4; +using blender::Set; using blender::Span; using blender::Vector; using blender::bke::GeometrySet; @@ -122,6 +124,11 @@ struct DupliContext { */ Vector *dupli_gen_type_stack; + /** + * If not null, then only instance objects that are in this set. + */ + Set *include_objects; + int persistent_id[MAX_DUPLI_RECUR]; int64_t instance_idx[MAX_DUPLI_RECUR]; const GeometrySet *instance_data[MAX_DUPLI_RECUR]; @@ -149,6 +156,7 @@ static void init_context(DupliContext *r_ctx, Scene *scene, Object *ob, const float space_mat[4][4], + blender::Set *include_objects, Vector &instance_stack, Vector &dupli_gen_type_stack) { @@ -177,6 +185,8 @@ static void init_context(DupliContext *r_ctx, r_ctx->duplilist = nullptr; r_ctx->preview_instance_index = -1; r_ctx->preview_base_geometry = nullptr; + + r_ctx->include_objects = include_objects; } /** @@ -535,17 +545,25 @@ static void make_duplis_collection(const DupliContext *ctx) eEvaluationMode mode = DEG_get_mode(ctx->depsgraph); FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (collection, cob, mode) { - if (cob != ob) { - float mat[4][4]; - - /* Collection dupli-offset, should apply after everything else. */ - mul_m4_m4m4(mat, collection_mat, cob->object_to_world().ptr()); - - make_dupli(ctx, cob, mat, _base_id); - - /* Recursion. */ - make_recursive_duplis(ctx, cob, collection_mat, _base_id); + if (cob == ob) { + continue; } + + if (ctx->include_objects) { + if (!ctx->include_objects->contains(cob)) { + continue; + } + } + + float mat[4][4]; + + /* Collection dupli-offset, should apply after everything else. */ + mul_m4_m4m4(mat, collection_mat, cob->object_to_world().ptr()); + + make_dupli(ctx, cob, mat, _base_id); + + /* Recursion. */ + make_recursive_duplis(ctx, cob, collection_mat, _base_id); } FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END; } @@ -1784,14 +1802,18 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx) /** \name Dupli-Container Implementation * \{ */ -ListBase *object_duplilist(Depsgraph *depsgraph, Scene *sce, Object *ob) +ListBase *object_duplilist(Depsgraph *depsgraph, + Scene *sce, + Object *ob, + Set *include_objects) { ListBase *duplilist = MEM_callocN("duplilist"); DupliContext ctx; Vector instance_stack; Vector dupli_gen_type_stack({0}); instance_stack.append(ob); - init_context(&ctx, depsgraph, sce, ob, nullptr, instance_stack, dupli_gen_type_stack); + init_context( + &ctx, depsgraph, sce, ob, nullptr, include_objects, instance_stack, dupli_gen_type_stack); if (ctx.gen) { ctx.duplilist = duplilist; ctx.gen->make_duplis(&ctx); @@ -1810,7 +1832,8 @@ ListBase *object_duplilist_preview(Depsgraph *depsgraph, Vector instance_stack; Vector dupli_gen_type_stack({0}); instance_stack.append(ob_eval); - init_context(&ctx, depsgraph, sce, ob_eval, nullptr, instance_stack, dupli_gen_type_stack); + init_context( + &ctx, depsgraph, sce, ob_eval, nullptr, nullptr, instance_stack, dupli_gen_type_stack); ctx.duplilist = duplilist; Object *ob_orig = DEG_get_original(ob_eval); @@ -1848,7 +1871,8 @@ blender::bke::Instances object_duplilist_legacy_instances(Depsgraph &depsgraph, Vector instance_stack({&ob}); Vector dupli_gen_type_stack({0}); - init_context(&ctx, &depsgraph, &scene, &ob, nullptr, instance_stack, dupli_gen_type_stack); + init_context( + &ctx, &depsgraph, &scene, &ob, nullptr, nullptr, instance_stack, dupli_gen_type_stack); if (ctx.gen == &gen_dupli_geometry_set) { /* These are not legacy instances. */ return {}; diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index 4cbef58e37f..1e17bc0fca9 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -286,7 +286,8 @@ bool deg_iterator_objects_step(DEGObjectIterData *data) ((object->transflag & OB_DUPLI) || object->runtime->geometry_set_eval != nullptr)) { BLI_assert(deg::deg_validate_eval_copy_datablock(&object->id)); - ListBase *duplis = object_duplilist(data->graph, data->scene, object); + ListBase *duplis = object_duplilist( + data->graph, data->scene, object, data->settings->included_objects); deg_iterator_duplis_init(data, object, duplis); } }