fix [#29616] Crash/infinite loop from missing cyclic check in group/dupligroups (unlikely/intentional)
calling BKE_ptcache_ids_from_object() could recursively call BKE_object_handle_update(), when there is no reason to update object transforms at all. Add option not to do any updates and just return an object list.
This commit is contained in:
@@ -65,6 +65,7 @@ int where_on_path(struct Object *ob, float ctime, float vec[4], float dir[3], fl
|
|||||||
/* ---------------------------------------------------- */
|
/* ---------------------------------------------------- */
|
||||||
/* Dupli-Geometry */
|
/* Dupli-Geometry */
|
||||||
|
|
||||||
|
struct ListBase *object_duplilist_ex(struct Scene *sce, struct Object *ob, int update);
|
||||||
struct ListBase *object_duplilist(struct Scene *sce, struct Object *ob);
|
struct ListBase *object_duplilist(struct Scene *sce, struct Object *ob);
|
||||||
void free_object_duplilist(struct ListBase *lb);
|
void free_object_duplilist(struct ListBase *lb);
|
||||||
int count_duplilist(struct Object *ob);
|
int count_duplilist(struct Object *ob);
|
||||||
|
@@ -74,7 +74,8 @@
|
|||||||
/* --------------------- */
|
/* --------------------- */
|
||||||
/* forward declarations */
|
/* forward declarations */
|
||||||
|
|
||||||
static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, int level, int animated);
|
static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index,
|
||||||
|
int level, short animated, short update);
|
||||||
|
|
||||||
/* ******************************************************************** */
|
/* ******************************************************************** */
|
||||||
/* Animation Visualization */
|
/* Animation Visualization */
|
||||||
@@ -699,7 +700,7 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua
|
|||||||
/* ******************************************************************** */
|
/* ******************************************************************** */
|
||||||
/* Dupli-Geometry */
|
/* Dupli-Geometry */
|
||||||
|
|
||||||
static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int par_index, int type, int animated)
|
static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int par_index, int type, short animated)
|
||||||
{
|
{
|
||||||
DupliObject *dob = MEM_callocN(sizeof(DupliObject), "dupliobject");
|
DupliObject *dob = MEM_callocN(sizeof(DupliObject), "dupliobject");
|
||||||
|
|
||||||
@@ -717,7 +718,8 @@ static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], i
|
|||||||
return dob;
|
return dob;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, int animated)
|
static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index,
|
||||||
|
int level, short animated, short update)
|
||||||
{
|
{
|
||||||
DupliObject *dob;
|
DupliObject *dob;
|
||||||
Group *group;
|
Group *group;
|
||||||
@@ -731,8 +733,14 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde
|
|||||||
if (level > MAX_DUPLI_RECUR) return;
|
if (level > MAX_DUPLI_RECUR) return;
|
||||||
|
|
||||||
/* handles animated groups, and */
|
/* handles animated groups, and */
|
||||||
|
|
||||||
/* we need to check update for objects that are not in scene... */
|
/* we need to check update for objects that are not in scene... */
|
||||||
|
if (update) {
|
||||||
|
/* note: update is optional because we don't always need object
|
||||||
|
* transformations to be correct. Also fixes bug [#29616]. */
|
||||||
group_handle_recalc_and_update(scene, ob, group);
|
group_handle_recalc_and_update(scene, ob, group);
|
||||||
|
}
|
||||||
|
|
||||||
animated = animated || group_is_animated(ob, group);
|
animated = animated || group_is_animated(ob, group);
|
||||||
|
|
||||||
for (go = group->gobject.first; go; go = go->next) {
|
for (go = group->gobject.first; go; go = go->next) {
|
||||||
@@ -764,14 +772,14 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde
|
|||||||
|
|
||||||
if (go->ob->transflag & OB_DUPLI) {
|
if (go->ob->transflag & OB_DUPLI) {
|
||||||
copy_m4_m4(dob->ob->obmat, dob->mat);
|
copy_m4_m4(dob->ob->obmat, dob->mat);
|
||||||
object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, animated);
|
object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, animated, update);
|
||||||
copy_m4_m4(dob->ob->obmat, dob->omat);
|
copy_m4_m4(dob->ob->obmat, dob->omat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, int animated)
|
static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, short animated)
|
||||||
{
|
{
|
||||||
extern int enable_cu_speed; /* object.c */
|
extern int enable_cu_speed; /* object.c */
|
||||||
Object copyob;
|
Object copyob;
|
||||||
@@ -843,7 +851,8 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_ind
|
|||||||
typedef struct VertexDupliData {
|
typedef struct VertexDupliData {
|
||||||
ID *id; /* scene or group, for recursive loops */
|
ID *id; /* scene or group, for recursive loops */
|
||||||
int level;
|
int level;
|
||||||
int animated;
|
short animated;
|
||||||
|
short update;
|
||||||
ListBase *lb;
|
ListBase *lb;
|
||||||
float pmat[4][4];
|
float pmat[4][4];
|
||||||
float obmat[4][4]; /* Only used for dupliverts inside dupligroups, where the ob->obmat is modified */
|
float obmat[4][4]; /* Only used for dupliverts inside dupligroups, where the ob->obmat is modified */
|
||||||
@@ -899,12 +908,13 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3],
|
|||||||
float tmpmat[4][4];
|
float tmpmat[4][4];
|
||||||
copy_m4_m4(tmpmat, vdd->ob->obmat);
|
copy_m4_m4(tmpmat, vdd->ob->obmat);
|
||||||
copy_m4_m4(vdd->ob->obmat, obmat); /* pretend we are really this mat */
|
copy_m4_m4(vdd->ob->obmat, obmat); /* pretend we are really this mat */
|
||||||
object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->animated);
|
object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->animated, vdd->update);
|
||||||
copy_m4_m4(vdd->ob->obmat, tmpmat);
|
copy_m4_m4(vdd->ob->obmat, tmpmat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, int level, int animated)
|
static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index,
|
||||||
|
int level, short animated, short update)
|
||||||
{
|
{
|
||||||
Object *ob, *ob_iter;
|
Object *ob, *ob_iter;
|
||||||
Mesh *me = par->data;
|
Mesh *me = par->data;
|
||||||
@@ -983,6 +993,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
|
|||||||
vdd.id = id;
|
vdd.id = id;
|
||||||
vdd.level = level;
|
vdd.level = level;
|
||||||
vdd.animated = animated;
|
vdd.animated = animated;
|
||||||
|
vdd.update = update;
|
||||||
vdd.lb = lb;
|
vdd.lb = lb;
|
||||||
vdd.ob = ob;
|
vdd.ob = ob;
|
||||||
vdd.scene = scene;
|
vdd.scene = scene;
|
||||||
@@ -1027,7 +1038,8 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
|
|||||||
dm->release(dm);
|
dm->release(dm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, int level, int animated)
|
static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index,
|
||||||
|
int level, short animated, short update)
|
||||||
{
|
{
|
||||||
Object *ob, *ob_iter;
|
Object *ob, *ob_iter;
|
||||||
Base *base = NULL;
|
Base *base = NULL;
|
||||||
@@ -1197,7 +1209,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
|
|||||||
float tmpmat[4][4];
|
float tmpmat[4][4];
|
||||||
copy_m4_m4(tmpmat, ob->obmat);
|
copy_m4_m4(tmpmat, ob->obmat);
|
||||||
copy_m4_m4(ob->obmat, obmat); /* pretend we are really this mat */
|
copy_m4_m4(ob->obmat, obmat); /* pretend we are really this mat */
|
||||||
object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, animated);
|
object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, animated, update);
|
||||||
copy_m4_m4(ob->obmat, tmpmat);
|
copy_m4_m4(ob->obmat, tmpmat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1217,7 +1229,8 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
|
|||||||
dm->release(dm);
|
dm->release(dm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int UNUSED(par_index), ParticleSystem *psys, int level, int animated)
|
static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int UNUSED(par_index), ParticleSystem *psys,
|
||||||
|
int level, short animated, short update)
|
||||||
{
|
{
|
||||||
GroupObject *go;
|
GroupObject *go;
|
||||||
Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL;
|
Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL;
|
||||||
@@ -1300,7 +1313,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
|
|||||||
|
|
||||||
/* gather list of objects or single object */
|
/* gather list of objects or single object */
|
||||||
if (part->ren_as == PART_DRAW_GR) {
|
if (part->ren_as == PART_DRAW_GR) {
|
||||||
|
if (update) {
|
||||||
group_handle_recalc_and_update(scene, par, part->dup_group);
|
group_handle_recalc_and_update(scene, par, part->dup_group);
|
||||||
|
}
|
||||||
|
|
||||||
if (part->draw & PART_DRAW_COUNT_GR) {
|
if (part->draw & PART_DRAW_COUNT_GR) {
|
||||||
for (dw = part->dupliweights.first; dw; dw = dw->next)
|
for (dw = part->dupliweights.first; dw; dw = dw->next)
|
||||||
@@ -1555,7 +1570,7 @@ static Object *find_family_object(Object **obar, char *family, char ch)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_index, int level, int animated)
|
static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_index, int level, short animated)
|
||||||
{
|
{
|
||||||
Object *ob, *obar[256] = {NULL};
|
Object *ob, *obar[256] = {NULL};
|
||||||
Curve *cu;
|
Curve *cu;
|
||||||
@@ -1603,7 +1618,8 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_inde
|
|||||||
|
|
||||||
/* ------------- */
|
/* ------------- */
|
||||||
|
|
||||||
static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, int level, int animated)
|
static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index,
|
||||||
|
int level, short animated, short update)
|
||||||
{
|
{
|
||||||
if ((ob->transflag & OB_DUPLI) == 0)
|
if ((ob->transflag & OB_DUPLI) == 0)
|
||||||
return;
|
return;
|
||||||
@@ -1623,11 +1639,11 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas
|
|||||||
if (ob->transflag & OB_DUPLIPARTS) {
|
if (ob->transflag & OB_DUPLIPARTS) {
|
||||||
ParticleSystem *psys = ob->particlesystem.first;
|
ParticleSystem *psys = ob->particlesystem.first;
|
||||||
for (; psys; psys = psys->next)
|
for (; psys; psys = psys->next)
|
||||||
new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, animated);
|
new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, animated, update);
|
||||||
}
|
}
|
||||||
else if (ob->transflag & OB_DUPLIVERTS) {
|
else if (ob->transflag & OB_DUPLIVERTS) {
|
||||||
if (ob->type == OB_MESH) {
|
if (ob->type == OB_MESH) {
|
||||||
vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated);
|
vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated, update);
|
||||||
}
|
}
|
||||||
else if (ob->type == OB_FONT) {
|
else if (ob->type == OB_FONT) {
|
||||||
if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */
|
if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */
|
||||||
@@ -1637,7 +1653,7 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas
|
|||||||
}
|
}
|
||||||
else if (ob->transflag & OB_DUPLIFACES) {
|
else if (ob->transflag & OB_DUPLIFACES) {
|
||||||
if (ob->type == OB_MESH)
|
if (ob->type == OB_MESH)
|
||||||
face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated);
|
face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated, update);
|
||||||
}
|
}
|
||||||
else if (ob->transflag & OB_DUPLIFRAMES) {
|
else if (ob->transflag & OB_DUPLIFRAMES) {
|
||||||
if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */
|
if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */
|
||||||
@@ -1647,7 +1663,7 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas
|
|||||||
else if (ob->transflag & OB_DUPLIGROUP) {
|
else if (ob->transflag & OB_DUPLIGROUP) {
|
||||||
DupliObject *dob;
|
DupliObject *dob;
|
||||||
|
|
||||||
group_duplilist(duplilist, scene, ob, par_index, level + 1, animated); /* now recursive */
|
group_duplilist(duplilist, scene, ob, par_index, level + 1, animated, update); /* now recursive */
|
||||||
|
|
||||||
if (level == 0) {
|
if (level == 0) {
|
||||||
for (dob = duplilist->first; dob; dob = dob->next)
|
for (dob = duplilist->first; dob; dob = dob->next)
|
||||||
@@ -1659,14 +1675,22 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas
|
|||||||
|
|
||||||
/* Returns a list of DupliObject
|
/* Returns a list of DupliObject
|
||||||
* note; group dupli's already set transform matrix. see note in group_duplilist() */
|
* note; group dupli's already set transform matrix. see note in group_duplilist() */
|
||||||
ListBase *object_duplilist(Scene *sce, Object *ob)
|
ListBase *object_duplilist_ex(Scene *sce, Object *ob, int update)
|
||||||
{
|
{
|
||||||
ListBase *duplilist = MEM_mallocN(sizeof(ListBase), "duplilist");
|
ListBase *duplilist = MEM_mallocN(sizeof(ListBase), "duplilist");
|
||||||
duplilist->first = duplilist->last = NULL;
|
duplilist->first = duplilist->last = NULL;
|
||||||
object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, 0);
|
object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, 0, update);
|
||||||
return duplilist;
|
return duplilist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* note: previously updating was always done, this is why it defaults to be on
|
||||||
|
* but there are likely places it can be called without updating */
|
||||||
|
ListBase *object_duplilist(Scene *sce, Object *ob)
|
||||||
|
{
|
||||||
|
return object_duplilist_ex(sce, ob, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void free_object_duplilist(ListBase *lb)
|
void free_object_duplilist(ListBase *lb)
|
||||||
{
|
{
|
||||||
DupliObject *dob;
|
DupliObject *dob;
|
||||||
|
@@ -1029,7 +1029,8 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
|
|||||||
if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) {
|
if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) {
|
||||||
ListBase *lb_dupli_ob;
|
ListBase *lb_dupli_ob;
|
||||||
|
|
||||||
if ((lb_dupli_ob=object_duplilist(scene, ob))) {
|
/* don't update the dupli groups, we only wan't their pid's */
|
||||||
|
if ((lb_dupli_ob = object_duplilist_ex(scene, ob, FALSE))) {
|
||||||
DupliObject *dob;
|
DupliObject *dob;
|
||||||
for (dob= lb_dupli_ob->first; dob; dob= dob->next) {
|
for (dob= lb_dupli_ob->first; dob; dob= dob->next) {
|
||||||
if (dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */
|
if (dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */
|
||||||
|
Reference in New Issue
Block a user