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:
authorJacques Lucke <jacques@blender.org>2021-04-27 13:35:48 +0300
committerJacques Lucke <jacques@blender.org>2021-04-27 13:35:48 +0300
commite240d94191c03297db7c3cb55cd788502ab77df9 (patch)
tree4fc27ceabdc62e69c2f4f267f6c7a0cd7df832dd
parent542f022afd1c3c6f444ee54707796ac03a317617 (diff)
parent7eb9b7976ff4e6ba820595dc59178f1ac189db3e (diff)
Merge branch 'blender-v2.93-release'
-rw-r--r--source/blender/blenkernel/intern/object_dupli.cc25
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);