From 653d645587cda2c7da878880cb027bd62c14257f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 12 Dec 2013 06:07:10 +0100 Subject: Fix T37769: inconsistent behavior of Remove Selected From Active Group. Add Selected to Active Group presented a menu with groups to choose from, while this seemingly inverse operation did not and used all groups of the active object. Now both operators present a menu, with as first option "All Groups". --- source/blender/editors/object/object_group.c | 150 +++++++++++++++++---------- 1 file changed, 97 insertions(+), 53 deletions(-) (limited to 'source/blender/editors/object/object_group.c') diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c index a9fd3ce1288..7e0bd2a4da7 100644 --- a/source/blender/editors/object/object_group.c +++ b/source/blender/editors/object/object_group.c @@ -117,11 +117,25 @@ static EnumPropertyItem *group_object_active_itemf(bContext *C, PointerRNA *UNUS ob = ED_object_context(C); - /* check that the action exists */ + /* check that the object exists */ if (ob) { - Group *group = NULL; - int i = 0; + Group *group; + int i = 0, count = 0; + /* if 2 or more groups, add option to add to all groups */ + group = NULL; + while ((group = BKE_group_object_find(group, ob))) + count++; + + if (count >= 2) { + item_tmp.identifier = item_tmp.name = "All Groups"; + item_tmp.value = INT_MAX; /* this will give NULL on lookup */ + RNA_enum_item_add(&item, &totitem, &item_tmp); + RNA_enum_item_add_separator(&item, &totitem); + } + + /* add groups */ + group = NULL; while ((group = BKE_group_object_find(group, ob))) { item_tmp.identifier = item_tmp.name = group->id.name + 2; /* item_tmp.icon = ICON_ARMATURE_DATA; */ @@ -157,44 +171,51 @@ static int objects_add_active_exec(bContext *C, wmOperator *op) Object *ob = ED_object_context(C); Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - int group_object_index = RNA_enum_get(op->ptr, "group"); - int is_cycle = FALSE; - - if (ob) { - Group *group = group_object_active_find_index(ob, group_object_index); - - /* now add all selected objects from the group */ - if (group) { + int single_group_index = RNA_enum_get(op->ptr, "group"); + Group *single_group = group_object_active_find_index(ob, single_group_index); + Group *group; + bool is_cycle = false; + bool updated = false; - /* for recursive check */ - tag_main_lb(&bmain->group, TRUE); + if (ob == NULL) + return OPERATOR_CANCELLED; - CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) - { - if (group_link_early_exit_check(group, base->object)) - continue; - - if (base->object->dup_group != group && !check_group_contains_object_recursive(group, base->object)) { - BKE_group_object_add(group, base->object, scene, base); - } - else { - is_cycle = TRUE; - } + /* now add all selected objects to the group(s) */ + for (group = bmain->group.first; group; group = group->id.next) { + if (single_group && group != single_group) + continue; + if (!BKE_group_object_exists(group, ob)) + continue; + + /* for recursive check */ + tag_main_lb(&bmain->group, TRUE); + + CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) + { + if (group_link_early_exit_check(group, base->object)) + continue; + + if (base->object->dup_group != group && !check_group_contains_object_recursive(group, base->object)) { + BKE_group_object_add(group, base->object, scene, base); + updated = true; } - CTX_DATA_END; - - if (is_cycle) { - BKE_report(op->reports, RPT_WARNING, "Skipped some groups because of cycle detected"); + else { + is_cycle = true; } - - DAG_relations_tag_update(bmain); - WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); - - return OPERATOR_FINISHED; } + CTX_DATA_END; } - return OPERATOR_CANCELLED; + if (is_cycle) + BKE_report(op->reports, RPT_WARNING, "Skipped some groups because of cycle detected"); + + if (!updated) + return OPERATOR_CANCELLED; + + DAG_relations_tag_update(bmain); + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + return OPERATOR_FINISHED; } void GROUP_OT_objects_add_active(wmOperatorType *ot) @@ -225,17 +246,23 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); Object *ob = OBACT; + int single_group_index = RNA_enum_get(op->ptr, "group"); + Group *single_group = group_object_active_find_index(ob, single_group_index); Group *group; int ok = 0; - if (!ob) return OPERATOR_CANCELLED; + if (ob == NULL) + return OPERATOR_CANCELLED; /* linking to same group requires its own loop so we can avoid * looking up the active objects groups each time */ for (group = bmain->group.first; group; group = group->id.next) { + if (single_group && group != single_group) + continue; + if (BKE_group_object_exists(group, ob)) { - /* Assign groups to selected objects */ + /* Remove groups from selected objects */ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { BKE_group_object_unlink(group, base->object, scene, base); @@ -245,7 +272,8 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op) } } - if (!ok) BKE_report(op->reports, RPT_ERROR, "Active object contains no groups"); + if (!ok) + BKE_report(op->reports, RPT_ERROR, "Active object contains no groups"); DAG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); @@ -255,6 +283,8 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op) void GROUP_OT_objects_remove_active(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Remove Selected From Active Group"; ot->description = "Remove the object from an object group that contains the active object"; @@ -262,10 +292,16 @@ void GROUP_OT_objects_remove_active(wmOperatorType *ot) /* api callbacks */ ot->exec = objects_remove_active_exec; + ot->invoke = WM_menu_invoke; ot->poll = ED_operator_objectmode; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "The group to remove other selected objects from"); + RNA_def_enum_funcs(prop, group_object_active_itemf); + ot->prop = prop; } static int group_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op)) @@ -305,28 +341,36 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op) Object *ob = ED_object_context(C); Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - int group_object_index = RNA_enum_get(op->ptr, "group"); - - if (ob) { - Group *group = group_object_active_find_index(ob, group_object_index); - - /* now remove all selected objects from the group */ - if (group) { + int single_group_index = RNA_enum_get(op->ptr, "group"); + Group *single_group = group_object_active_find_index(ob, single_group_index); + Group *group; + bool updated = false; - CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) - { - BKE_group_object_unlink(group, base->object, scene, base); - } - CTX_DATA_END; + if (ob == NULL) + return OPERATOR_CANCELLED; - DAG_relations_tag_update(bmain); - WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + for (group = bmain->group.first; group; group = group->id.next) { + if (single_group && group != single_group) + continue; + if (!BKE_group_object_exists(group, ob)) + continue; - return OPERATOR_FINISHED; + /* now remove all selected objects from the group */ + CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) + { + BKE_group_object_unlink(group, base->object, scene, base); + updated = true; } + CTX_DATA_END; } - return OPERATOR_CANCELLED; + if (!updated) + return OPERATOR_CANCELLED; + + DAG_relations_tag_update(bmain); + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + return OPERATOR_FINISHED; } void GROUP_OT_objects_remove(wmOperatorType *ot) -- cgit v1.2.3