diff options
author | Jacques Lucke <jacques@blender.org> | 2021-04-27 13:35:48 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-04-27 13:35:48 +0300 |
commit | e240d94191c03297db7c3cb55cd788502ab77df9 (patch) | |
tree | 4fc27ceabdc62e69c2f4f267f6c7a0cd7df832dd /source/blender/blenkernel/intern | |
parent | 542f022afd1c3c6f444ee54707796ac03a317617 (diff) | |
parent | 7eb9b7976ff4e6ba820595dc59178f1ac189db3e (diff) |
Merge branch 'blender-v2.93-release'
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/object_dupli.cc | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index ddf7826969b..835b62c06bf 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -36,6 +36,7 @@ #include "BLI_math.h" #include "BLI_rand.h" #include "BLI_span.hh" +#include "BLI_vector.hh" #include "DNA_anim_types.h" #include "DNA_collection_types.h" @@ -73,6 +74,7 @@ using blender::Array; using blender::float3; using blender::float4x4; using blender::Span; +using blender::Vector; /* -------------------------------------------------------------------- */ /** \name Internal Duplicate Context @@ -90,6 +92,13 @@ struct DupliContext { Object *object; float space_mat[4][4]; + /** + * A stack that contains all the "parent" objects of a particular instance when recursive + * instancing is used. This is used to prevent objects from instancing themselves accidentally. + * Use a vector instead of a stack because we want to use the #contains method. + */ + Vector<Object *> *instance_stack; + int persistent_id[MAX_DUPLI_RECUR]; int level; @@ -113,7 +122,8 @@ static void init_context(DupliContext *r_ctx, Depsgraph *depsgraph, Scene *scene, Object *ob, - const float space_mat[4][4]) + const float space_mat[4][4], + Vector<Object *> &instance_stack) { r_ctx->depsgraph = depsgraph; r_ctx->scene = scene; @@ -122,6 +132,7 @@ static void init_context(DupliContext *r_ctx, r_ctx->object = ob; r_ctx->obedit = OBEDIT_FROM_OBACT(ob); + r_ctx->instance_stack = &instance_stack; if (space_mat) { copy_m4_m4(r_ctx->space_mat, space_mat); } @@ -150,6 +161,7 @@ static void copy_dupli_context( } r_ctx->object = ob; + r_ctx->instance_stack = ctx->instance_stack; if (mat) { mul_m4_m4m4(r_ctx->space_mat, (float(*)[4])ctx->space_mat, mat); } @@ -235,12 +247,19 @@ static void make_recursive_duplis(const DupliContext *ctx, const float space_mat[4][4], int index) { + if (ctx->instance_stack->contains(ob)) { + /* Avoid recursive instances. */ + printf("Warning: '%s' object is trying to instance itself.\n", ob->id.name + 2); + return; + } /* Simple preventing of too deep nested collections with #MAX_DUPLI_RECUR. */ if (ctx->level < MAX_DUPLI_RECUR) { DupliContext rctx; copy_dupli_context(&rctx, ctx, ob, space_mat, index); if (rctx.gen) { + ctx->instance_stack->append(ob); rctx.gen->make_duplis(&rctx); + ctx->instance_stack->remove_last(); } } } @@ -1588,7 +1607,9 @@ ListBase *object_duplilist(Depsgraph *depsgraph, Scene *sce, Object *ob) { ListBase *duplilist = (ListBase *)MEM_callocN(sizeof(ListBase), "duplilist"); DupliContext ctx; - init_context(&ctx, depsgraph, sce, ob, nullptr); + Vector<Object *> instance_stack; + instance_stack.append(ob); + init_context(&ctx, depsgraph, sce, ob, nullptr, instance_stack); if (ctx.gen) { ctx.duplilist = duplilist; ctx.gen->make_duplis(&ctx); |