diff options
-rw-r--r-- | source/blender/blenkernel/BKE_object.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 31 | ||||
-rw-r--r-- | source/blender/editors/object/object_group.c | 13 | ||||
-rw-r--r-- | source/blender/editors/object/object_relations.c | 96 |
4 files changed, 108 insertions, 34 deletions
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index b8ba3095905..3aa7148d821 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -177,6 +177,8 @@ typedef enum eObjectSet { } eObjectSet; struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter); +struct LinkNode *BKE_object_groups(struct Object *ob); +void BKE_object_groups_clear(struct Scene *scene, struct Base *base, struct Object *object); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index a3145ddeedd..048560f3a83 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -3156,7 +3156,7 @@ static void obrel_list_add(LinkNode **links, Object *ob) * If OB_SET_VISIBLE or OB_SET_SELECTED are collected, * then also add related objects according to the given includeFilters. */ -struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter) +LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter) { LinkNode *links = NULL; @@ -3235,3 +3235,32 @@ struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet return links; } + +/** + * return all groups this object is apart of, caller must free. + */ +struct LinkNode *BKE_object_groups(Object *ob) +{ + LinkNode *group_linknode = NULL; + Group *group = NULL; + while ((group = find_group(ob, group))) { + BLI_linklist_prepend(&group_linknode, group); + } + + return group_linknode; +} + +void BKE_object_groups_clear(Scene *scene, Base *base, Object *object) +{ + Group *group = NULL; + + BLI_assert(base->object == object); + + if (scene && base == NULL) { + base = BKE_scene_base_find(scene, object); + } + + while ((group = find_group(base->object, group))) { + rem_from_group(group, object, scene, base); + } +} diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c index 3b9d54d76d6..e86a62f0dca 100644 --- a/source/blender/editors/object/object_group.c +++ b/source/blender/editors/object/object_group.c @@ -44,6 +44,7 @@ #include "BKE_group.h" #include "BKE_main.h" #include "BKE_report.h" +#include "BKE_object.h" #include "ED_screen.h" #include "ED_object.h" @@ -113,7 +114,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); int group_object_index = RNA_enum_get(op->ptr, "group"); - int cycle = FALSE; + int is_cycle = FALSE; if (ob) { Group *group = group_object_active_find_index(ob, group_object_index); @@ -127,7 +128,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op) add_to_group(group, base->object, scene, base); } else { - cycle = TRUE; + is_cycle = TRUE; } } CTX_DATA_END; @@ -139,8 +140,9 @@ static int objects_add_active_exec(bContext *C, wmOperator *op) } } - if (cycle) + if (is_cycle) { BKE_report(op->reports, RPT_WARNING, "Skipped some groups because of cycle detected"); + } return OPERATOR_CANCELLED; } @@ -220,13 +222,10 @@ static int group_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Group *group = NULL; CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { - group = NULL; - while ((group = find_group(base->object, group))) - rem_from_group(group, base->object, scene, base); + BKE_object_groups_clear(scene, base, base->object); } CTX_DATA_END; diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 860ff24cafd..d25e41898ea 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -50,6 +50,7 @@ #include "BLI_math.h" #include "BLI_listbase.h" +#include "BLI_linklist.h" #include "BLI_string.h" #include "BLI_utildefines.h" @@ -64,6 +65,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_displist.h" #include "BKE_global.h" +#include "BKE_group.h" #include "BKE_fcurve.h" #include "BKE_lamp.h" #include "BKE_lattice.h" @@ -1277,14 +1279,15 @@ enum { MAKE_LINKS_OBDATA = 1, MAKE_LINKS_MATERIALS, MAKE_LINKS_ANIMDATA, + MAKE_LINKS_GROUP, MAKE_LINKS_DUPLIGROUP, MAKE_LINKS_MODIFIERS }; /* Return 1 if make link data is allow, zero otherwise */ -static int allow_make_links_data(int ev, Object *ob, Object *obt) +static int allow_make_links_data(const int type, Object *ob, Object *obt) { - switch (ev) { + switch (type) { case MAKE_LINKS_OBDATA: if (ob->type == obt->type && ob->type != OB_EMPTY) return 1; @@ -1297,6 +1300,7 @@ static int allow_make_links_data(int ev, Object *ob, Object *obt) } break; case MAKE_LINKS_ANIMDATA: + case MAKE_LINKS_GROUP: case MAKE_LINKS_DUPLIGROUP: return 1; case MAKE_LINKS_MODIFIERS: @@ -1310,52 +1314,81 @@ static int allow_make_links_data(int ev, Object *ob, Object *obt) static int make_links_data_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - int event = RNA_enum_get(op->ptr, "type"); - Object *ob; + Scene *scene = CTX_data_scene(C); + const int type = RNA_enum_get(op->ptr, "type"); + Object *ob_src; ID *id; int a; - ob = ED_object_active_context(C); + /* group */ + LinkNode *ob_groups = NULL; + int is_cycle = FALSE; + + ob_src = ED_object_active_context(C); + + /* avoid searching all groups in source object each time */ + if (type == MAKE_LINKS_GROUP) { + ob_groups = BKE_object_groups(ob_src); + } - CTX_DATA_BEGIN (C, Object *, obt, selected_editable_objects) + CTX_DATA_BEGIN (C, Base *, base_dst, selected_editable_bases) { - if (ob != obt) { - if (allow_make_links_data(event, ob, obt)) { - switch (event) { + Object *ob_dst = base_dst->object; + + if (ob_src != ob_dst) { + if (allow_make_links_data(type, ob_src, ob_dst)) { + switch (type) { case MAKE_LINKS_OBDATA: /* obdata */ - id = obt->data; + id = ob_dst->data; id->us--; - id = ob->data; + id = ob_src->data; id_us_plus(id); - obt->data = id; + ob_dst->data = id; /* if amount of material indices changed: */ - test_object_materials(obt->data); + test_object_materials(ob_dst->data); - obt->recalc |= OB_RECALC_DATA; + ob_dst->recalc |= OB_RECALC_DATA; break; case MAKE_LINKS_MATERIALS: /* new approach, using functions from kernel */ - for (a = 0; a < ob->totcol; a++) { - Material *ma = give_current_material(ob, a + 1); - assign_material(obt, ma, a + 1); /* also works with ma==NULL */ + for (a = 0; a < ob_src->totcol; a++) { + Material *ma = give_current_material(ob_src, a + 1); + assign_material(ob_dst, ma, a + 1); /* also works with ma==NULL */ } break; case MAKE_LINKS_ANIMDATA: - BKE_copy_animdata_id((ID *)obt, (ID *)ob, FALSE); - BKE_copy_animdata_id((ID *)obt->data, (ID *)ob->data, FALSE); + BKE_copy_animdata_id((ID *)ob_dst, (ID *)ob_src, FALSE); + BKE_copy_animdata_id((ID *)ob_dst->data, (ID *)ob_src->data, FALSE); break; + case MAKE_LINKS_GROUP: + { + LinkNode *group_node; + + /* first clear groups */ + BKE_object_groups_clear(scene, base_dst, ob_dst); + + /* now add in the groups from the link nodes */ + for (group_node = ob_groups; group_node; group_node = group_node->next) { + if (ob_dst->dup_group != group_node->link) { + add_to_group(group_node->link, ob_dst, scene, base_dst); + } + else { + is_cycle = TRUE; + } + } + } case MAKE_LINKS_DUPLIGROUP: - obt->dup_group = ob->dup_group; - if (obt->dup_group) { - id_lib_extern(&obt->dup_group->id); - obt->transflag |= OB_DUPLIGROUP; + ob_dst->dup_group = ob_src->dup_group; + if (ob_dst->dup_group) { + id_lib_extern(&ob_dst->dup_group->id); + ob_dst->transflag |= OB_DUPLIGROUP; } break; case MAKE_LINKS_MODIFIERS: - BKE_object_link_modifiers(obt, ob); - obt->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; + BKE_object_link_modifiers(ob_dst, ob_src); + ob_dst->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; break; } } @@ -1363,7 +1396,17 @@ static int make_links_data_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - DAG_scene_sort(bmain, CTX_data_scene(C)); + if (type == MAKE_LINKS_GROUP) { + if (ob_groups) { + BLI_linklist_free(ob_groups, NULL); + } + + if (is_cycle) { + BKE_report(op->reports, RPT_WARNING, "Skipped some groups because of cycle detected"); + } + } + + DAG_scene_sort(bmain, scene); DAG_ids_flush_update(bmain, 0); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); @@ -1400,6 +1443,7 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot) {MAKE_LINKS_OBDATA, "OBDATA", 0, "Object Data", ""}, {MAKE_LINKS_MATERIALS, "MATERIAL", 0, "Materials", ""}, {MAKE_LINKS_ANIMDATA, "ANIMATION", 0, "Animation Data", ""}, + {MAKE_LINKS_GROUP, "GROUPS", 0, "Group", ""}, {MAKE_LINKS_DUPLIGROUP, "DUPLIGROUP", 0, "DupliGroup", ""}, {MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Modifiers", ""}, {0, NULL, 0, NULL, NULL}}; |