// copied from /editors/object/object_relations.c int bc_test_parent_loop(Object *par, Object *ob) { /* test if 'ob' is a parent somewhere in par's parents */ if (par == NULL) return 0; if (ob == par) return 1; return bc_test_parent_loop(par->parent, ob); }
// a shortened version of parent_set_exec() // if is_parent_space is true then ob->obmat will be multiplied by par->obmat before parenting int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space) { Object workob; Scene *sce = CTX_data_scene(C); if (!par || bc_test_parent_loop(par, ob)) return false; ob->parent = par; ob->partype = PAROBJECT; ob->parsubstr[0] = 0; if (is_parent_space) { float mat[4][4]; // calc par->obmat BKE_object_where_is_calc(sce, par); // move child obmat into world space mul_m4_m4m4(mat, par->obmat, ob->obmat); copy_m4_m4(ob->obmat, mat); } // apply child obmat (i.e. decompose it into rot/loc/size) BKE_object_apply_mat4(ob, ob->obmat, 0, 0); // compute parentinv BKE_object_workob_calc_parent(sce, ob, &workob); invert_m4_m4(ob->parentinv, workob.obmat); DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); DAG_id_tag_update(&par->id, OB_RECALC_OB); /** done once after import */ #if 0 DAG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); #endif return true; }
// a shortened version of parent_set_exec() // if is_parent_space is true then ob->obmat will be multiplied by par->obmat before parenting int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space) { Object workob; Main *bmain = CTX_data_main(C); Scene *sce = CTX_data_scene(C); if (!par || bc_test_parent_loop(par, ob)) return false; ob->parent = par; ob->partype = PAROBJECT; ob->parsubstr[0] = 0; if (is_parent_space) { float mat[4][4]; // calc par->obmat where_is_object(sce, par); // move child obmat into world space mul_m4_m4m4(mat, ob->obmat, par->obmat); copy_m4_m4(ob->obmat, mat); } // apply child obmat (i.e. decompose it into rot/loc/size) object_apply_mat4(ob, ob->obmat, 0, 0); // compute parentinv what_does_parent(sce, ob, &workob); invert_m4_m4(ob->parentinv, workob.obmat); ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA; par->recalc |= OB_RECALC_OB; DAG_scene_sort(bmain, sce); DAG_ids_flush_update(bmain, 0); WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); return true; }