Index: release/scripts/presets/keyconfig/maya.py =================================================================== --- release/scripts/presets/keyconfig/maya.py (revision 50166) +++ release/scripts/presets/keyconfig/maya.py (working copy) @@ -291,9 +291,8 @@ kmi = km.keymap_items.new('anim.keyframe_insert_menu', 'I', 'PRESS') kmi = km.keymap_items.new('anim.keyframe_delete_v3d', 'I', 'PRESS', alt=True) kmi = km.keymap_items.new('anim.keying_set_active_set', 'I', 'PRESS', shift=True, ctrl=True, alt=True) kmi = km.keymap_items.new('group.create', 'G', 'PRESS', ctrl=True) -kmi = km.keymap_items.new('group.objects_remove', 'G', 'PRESS', ctrl=True, alt=True) -kmi = km.keymap_items.new('group.objects_add_active', 'G', 'PRESS', shift=True, ctrl=True) -kmi = km.keymap_items.new('group.objects_remove_active', 'G', 'PRESS', shift=True, alt=True) +kmi = km.keymap_items.new('group.add_selected', 'G', 'PRESS', shift=True, ctrl=True) +kmi = km.keymap_items.new('group.remove_selected', 'G', 'PRESS', shift=True, alt=True) kmi = km.keymap_items.new('wm.call_menu', 'W', 'PRESS', ctrl=True) kmi.properties.name = 'VIEW3D_MT_object_specials' kmi = km.keymap_items.new('object.subdivision_set', 'ZERO', 'PRESS', ctrl=True) Index: release/scripts/startup/bl_ui/space_view3d.py =================================================================== --- release/scripts/startup/bl_ui/space_view3d.py (revision 50166) +++ release/scripts/startup/bl_ui/space_view3d.py (working copy) @@ -987,8 +987,6 @@ class VIEW3D_MT_object_group(Menu): layout = self.layout layout.operator("group.create") - # layout.operator_menu_enum("group.objects_remove", "group") # BUGGY - layout.operator("group.objects_remove") layout.operator("group.objects_remove_all") layout.separator() @@ -996,6 +994,11 @@ class VIEW3D_MT_object_group(Menu): layout.operator("group.objects_add_active") layout.operator("group.objects_remove_active") + layout.separator() + + layout.operator("group.add_selected") + layout.operator("group.remove_selected") + class VIEW3D_MT_object_constraints(Menu): bl_label = "Constraints" Index: source/blender/editors/object/object_group.c =================================================================== --- source/blender/editors/object/object_group.c (revision 50166) +++ source/blender/editors/object/object_group.c (working copy) @@ -185,7 +185,7 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op) for (group = bmain->group.first; group; group = group->id.next) { if (object_in_group(ob, group)) { - /* Assign groups to selected objects */ + /* Remove group from selected objects */ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { rem_from_group(group, base->object, scene, base); @@ -218,6 +218,143 @@ void GROUP_OT_objects_remove_active(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +static int group_add_selected_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + Group *group = BLI_findlink(&CTX_data_main(C)->group, RNA_enum_get(op->ptr, "group")); + int ok = FALSE, is_cycle = FALSE; + + /* Assign group to selected objects */ + CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) + { + if (base->object->dup_group != group) { + add_to_group(group, base->object, scene, base); + } + else { + is_cycle = TRUE; + } + ok = TRUE; + } + CTX_DATA_END; + + if (!ok) { + BKE_report(op->reports, RPT_ERROR, "No objects selected"); + } + if (is_cycle) { + BKE_report(op->reports, RPT_WARNING, "Skipped some groups because of cycle detected"); + } + + DAG_scene_sort(bmain, scene); + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GROUP_OT_add_selected(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Add Selected to Group"; + ot->idname = "GROUP_OT_add_selected"; + ot->description = "Add all selected objects to an existing group"; + + /* api callbacks */ + ot->exec = group_add_selected_exec; + ot->invoke = WM_enum_search_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", ""); + RNA_def_enum_funcs(prop, RNA_group_local_itemf); + ot->prop = prop; +} + +/* Only add items for groups that the selected objects are in*/ +static EnumPropertyItem *group_remove_selected_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), + int *do_free) +{ + EnumPropertyItem item_tmp = {0}, *item = NULL; + int totitem = 0; + int i = 0; + ID *id = C ? (ID *)CTX_data_main(C)->group.first : NULL; + + /* loop through groups first */ + for (; id; id = id->next) { + /* only get local groups, why? This is what is done in RNA_group_local_itemf */ + if (id->lib == NULL) { + /* if this group is part of any object, add to enum list and break */ + CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) + { + if (object_in_group(base->object, (Group *) id)) { + item_tmp.identifier = item_tmp.name = id->name + 2; + item_tmp.value = i; + RNA_enum_item_add(&item, &totitem, &item_tmp); + break; + } + } + CTX_DATA_END; + } + /* increment i at end for each group because the value is used to find group in the main list */ + i++; + } + + RNA_enum_item_end(&item, &totitem); + *do_free = TRUE; + + return item; +} + +static int group_remove_selected_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + Group *group = BLI_findlink(&CTX_data_main(C)->group, RNA_enum_get(op->ptr, "group")); + int ok = FALSE; + + /* Remove group from selected objects */ + CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) + { + rem_from_group(group, base->object, scene, base); + ok = TRUE; + } + CTX_DATA_END; + + if (!ok) { + BKE_report(op->reports, RPT_ERROR, "No objects selected"); + } + + DAG_scene_sort(bmain, scene); + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GROUP_OT_remove_selected(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Remove Selected from Group"; + ot->idname = "GROUP_OT_remove_selected"; + ot->description = "Remove all selected objects from an existing group"; + + /* api callbacks */ + ot->exec = group_remove_selected_exec; + ot->invoke = WM_enum_search_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", ""); + RNA_def_enum_funcs(prop, group_remove_selected_itemf); + ot->prop = prop; +} + static int group_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); @@ -250,58 +387,6 @@ void GROUP_OT_objects_remove_all(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -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) { - - CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) - { - rem_from_group(group, base->object, scene, base); - } - CTX_DATA_END; - - DAG_scene_sort(bmain, scene); - WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); - - return OPERATOR_FINISHED; - } - } - - return OPERATOR_CANCELLED; -} - -void GROUP_OT_objects_remove(wmOperatorType *ot) -{ - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Remove From Group"; - ot->description = "Remove selected objects from all groups or a selected group"; - ot->idname = "GROUP_OT_objects_remove"; - - /* api callbacks */ - ot->exec = group_objects_remove_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 this object from"); - RNA_def_enum_funcs(prop, group_object_active_itemf); - ot->prop = prop; -} - static int group_create_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Index: source/blender/editors/object/object_intern.h =================================================================== --- source/blender/editors/object/object_intern.h (revision 50166) +++ source/blender/editors/object/object_intern.h (working copy) @@ -141,9 +141,10 @@ void LATTICE_OT_make_regular(struct wmOperatorType *ot); /* object_group.c */ void GROUP_OT_create(struct wmOperatorType *ot); void GROUP_OT_objects_remove_all(struct wmOperatorType *ot); -void GROUP_OT_objects_remove(struct wmOperatorType *ot); void GROUP_OT_objects_add_active(struct wmOperatorType *ot); void GROUP_OT_objects_remove_active(struct wmOperatorType *ot); +void GROUP_OT_add_selected(wmOperatorType *ot); +void GROUP_OT_remove_selected(wmOperatorType *ot); /* object_modifier.c */ void OBJECT_OT_modifier_add(struct wmOperatorType *ot); Index: source/blender/editors/object/object_ops.c =================================================================== --- source/blender/editors/object/object_ops.c (revision 50166) +++ source/blender/editors/object/object_ops.c (working copy) @@ -106,9 +106,10 @@ void ED_operatortypes_object(void) WM_operatortype_append(GROUP_OT_create); WM_operatortype_append(GROUP_OT_objects_remove_all); - WM_operatortype_append(GROUP_OT_objects_remove); WM_operatortype_append(GROUP_OT_objects_add_active); WM_operatortype_append(GROUP_OT_objects_remove_active); + WM_operatortype_append(GROUP_OT_add_selected); + WM_operatortype_append(GROUP_OT_remove_selected); WM_operatortype_append(OBJECT_OT_delete); WM_operatortype_append(OBJECT_OT_text_add); @@ -394,10 +395,9 @@ void ED_keymap_object(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "ANIM_OT_keying_set_active_set", IKEY, KM_PRESS, KM_CTRL | KM_SHIFT | KM_ALT, 0); WM_keymap_verify_item(keymap, "GROUP_OT_create", GKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove", GKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_all", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL | KM_ALT, 0); - WM_keymap_verify_item(keymap, "GROUP_OT_objects_add_active", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); - WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_active", GKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0); + WM_keymap_verify_item(keymap, "GROUP_OT_add_selected", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); + WM_keymap_verify_item(keymap, "GROUP_OT_remove_selected", GKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_add_menu(keymap, "VIEW3D_MT_object_specials", WKEY, KM_PRESS, 0, 0);