2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * Contributor(s): Blender Foundation, 2002-2008 full recode
23 * ***** END GPL LICENSE BLOCK *****
26 /** \file blender/editors/object/object_select.c
36 #include "MEM_guardedalloc.h"
38 #include "DNA_anim_types.h"
39 #include "DNA_group_types.h"
40 #include "DNA_material_types.h"
41 #include "DNA_modifier_types.h"
42 #include "DNA_property_types.h"
43 #include "DNA_scene_types.h"
44 #include "DNA_armature_types.h"
47 #include "BLI_listbase.h"
49 #include "BLI_string.h"
50 #include "BLI_utildefines.h"
52 #include "BKE_context.h"
53 #include "BKE_group.h"
55 #include "BKE_material.h"
56 #include "BKE_particle.h"
57 #include "BKE_property.h"
58 #include "BKE_report.h"
59 #include "BKE_scene.h"
60 #include "BKE_library.h"
61 #include "BKE_deform.h"
66 #include "ED_object.h"
67 #include "ED_screen.h"
68 #include "ED_keyframing.h"
70 #include "UI_interface.h"
71 #include "UI_resources.h"
73 #include "RNA_access.h"
74 #include "RNA_define.h"
75 #include "RNA_enum_types.h"
77 #include "object_intern.h"
79 /************************ Exported **************************/
81 /* simple API for object selection, rather than just using the flag
82 * this takes into account the 'restrict selection in 3d view' flag.
83 * deselect works always, the restriction just prevents selection */
85 /* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! (or
86 * or a NC_SCENE|ND_OB_VISIBLE in case of visibility toggling */
88 void ED_base_object_select(Base *base, short mode)
91 if (mode == BA_SELECT) {
92 if (!(base->object->restrictflag & OB_RESTRICT_SELECT))
95 else if (mode == BA_DESELECT) {
96 base->flag &= ~SELECT;
98 base->object->flag = base->flag;
102 /* also to set active NULL */
103 void ED_base_object_activate(bContext *C, Base *base)
105 Scene *scene = CTX_data_scene(C);
107 /* sets scene->basact */
112 /* XXX old signals, remember to handle notifiers now! */
113 // select_actionchannel_by_name(base->object->action, "Object", 1);
115 WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
118 WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, NULL);
121 /********************** Selection Operators **********************/
123 static int objects_selectable_poll(bContext *C)
125 /* we don't check for linked scenes here, selection is
126 * still allowed then for inspection of scene */
127 Object *obact = CTX_data_active_object(C);
129 if (CTX_data_edit_object(C))
131 if (obact && obact->mode)
137 /************************ Select by Type *************************/
139 static int object_select_by_type_exec(bContext *C, wmOperator *op)
141 short obtype, extend;
143 obtype = RNA_enum_get(op->ptr, "type");
144 extend = RNA_boolean_get(op->ptr, "extend");
147 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
149 ED_base_object_select(base, BA_DESELECT);
154 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
156 if (base->object->type == obtype) {
157 ED_base_object_select(base, BA_SELECT);
162 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
164 return OPERATOR_FINISHED;
167 void OBJECT_OT_select_by_type(wmOperatorType *ot)
170 ot->name = "Select By Type";
171 ot->description = "Select all visible objects that are of a type";
172 ot->idname = "OBJECT_OT_select_by_type";
175 ot->invoke = WM_menu_invoke;
176 ot->exec = object_select_by_type_exec;
177 ot->poll = objects_selectable_poll;
180 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
183 RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
184 ot->prop = RNA_def_enum(ot->srna, "type", object_type_items, 1, "Type", "");
187 /*********************** Selection by Links *********************/
190 OBJECT_SELECT_LINKED_IPO = 1,
191 OBJECT_SELECT_LINKED_OBDATA,
192 OBJECT_SELECT_LINKED_MATERIAL,
193 OBJECT_SELECT_LINKED_TEXTURE,
194 OBJECT_SELECT_LINKED_DUPGROUP,
195 OBJECT_SELECT_LINKED_PARTICLE,
196 OBJECT_SELECT_LINKED_LIBRARY,
197 OBJECT_SELECT_LINKED_LIBRARY_OBDATA
200 static EnumPropertyItem prop_select_linked_types[] = {
201 //{OBJECT_SELECT_LINKED_IPO, "IPO", 0, "Object IPO", ""}, // XXX depreceated animation system stuff...
202 {OBJECT_SELECT_LINKED_OBDATA, "OBDATA", 0, "Object Data", ""},
203 {OBJECT_SELECT_LINKED_MATERIAL, "MATERIAL", 0, "Material", ""},
204 {OBJECT_SELECT_LINKED_TEXTURE, "TEXTURE", 0, "Texture", ""},
205 {OBJECT_SELECT_LINKED_DUPGROUP, "DUPGROUP", 0, "Dupligroup", ""},
206 {OBJECT_SELECT_LINKED_PARTICLE, "PARTICLE", 0, "Particle System", ""},
207 {OBJECT_SELECT_LINKED_LIBRARY, "LIBRARY", 0, "Library", ""},
208 {OBJECT_SELECT_LINKED_LIBRARY_OBDATA, "LIBRARY_OBDATA", 0, "Library (Object Data)", ""},
209 {0, NULL, 0, NULL, NULL}
212 // XXX old animation system
214 static int object_select_all_by_ipo(bContext *C, Ipo *ipo)
218 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
220 if (base->object->ipo == ipo) {
221 base->flag |= SELECT;
222 base->object->flag = base->flag;
233 static int object_select_all_by_obdata(bContext *C, void *obdata)
237 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
239 if ((base->flag & SELECT) == 0) {
240 if (base->object->data == obdata) {
241 base->flag |= SELECT;
242 base->object->flag = base->flag;
253 static int object_select_all_by_material_texture(bContext *C, int use_texture, Material *mat, Tex *tex)
257 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
259 if ((base->flag & SELECT) == 0) {
260 Object *ob = base->object;
264 for (a = 1; a <= ob->totcol; a++) {
265 mat1 = give_current_material(ob, a);
269 base->flag |= SELECT;
273 else if (mat1 && use_texture) {
274 for (b = 0; b < MAX_MTEX; b++) {
276 if (tex == mat1->mtex[b]->tex) {
277 base->flag |= SELECT;
286 base->object->flag = base->flag;
294 static int object_select_all_by_dup_group(bContext *C, Object *ob)
297 Group *dup_group = (ob->transflag & OB_DUPLIGROUP) ? ob->dup_group : NULL;
299 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
301 if ((base->flag & SELECT) == 0) {
302 Group *dup_group_other = (base->object->transflag & OB_DUPLIGROUP) ? base->object->dup_group : NULL;
303 if (dup_group == dup_group_other) {
304 base->flag |= SELECT;
305 base->object->flag = base->flag;
316 static int object_select_all_by_particle(bContext *C, Object *ob)
320 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
322 if ((base->flag & SELECT) == 0) {
323 /* loop through other, then actives particles*/
324 ParticleSystem *psys;
325 ParticleSystem *psys_act;
327 for (psys = base->object->particlesystem.first; psys; psys = psys->next) {
328 for (psys_act = ob->particlesystem.first; psys_act; psys_act = psys_act->next) {
329 if (psys->part == psys_act->part) {
330 base->flag |= SELECT;
336 if (base->flag & SELECT) {
341 base->object->flag = base->flag;
349 static int object_select_all_by_library(bContext *C, Library *lib)
353 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
355 if ((base->flag & SELECT) == 0) {
356 if (lib == base->object->id.lib) {
357 base->flag |= SELECT;
358 base->object->flag = base->flag;
369 static int object_select_all_by_library_obdata(bContext *C, Library *lib)
373 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
375 if ((base->flag & SELECT) == 0) {
376 if (base->object->data && lib == ((ID *)base->object->data)->lib) {
377 base->flag |= SELECT;
378 base->object->flag = base->flag;
389 void ED_object_select_linked_by_id(bContext *C, ID *id)
391 int gs = GS(id->name);
394 if (ELEM8(gs, ID_ME, ID_CU, ID_MB, ID_LT, ID_LA, ID_CA, ID_TXT, ID_SPK)) {
395 changed = object_select_all_by_obdata(C, id);
397 else if (gs == ID_MA) {
398 changed = object_select_all_by_material_texture(C, FALSE, (Material *)id, NULL);
400 else if (gs == ID_LI) {
401 changed = object_select_all_by_library(C, (Library *) id);
405 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
408 static int object_select_linked_exec(bContext *C, wmOperator *op)
410 Scene *scene = CTX_data_scene(C);
412 int nr = RNA_enum_get(op->ptr, "type");
413 short changed = FALSE, extend;
415 extend = RNA_boolean_get(op->ptr, "extend");
418 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
420 ED_base_object_select(base, BA_DESELECT);
427 BKE_report(op->reports, RPT_ERROR, "No Active Object");
428 return OPERATOR_CANCELLED;
431 if (nr == OBJECT_SELECT_LINKED_IPO) {
432 // XXX old animation system
433 //if (ob->ipo == 0) return OPERATOR_CANCELLED;
434 //object_select_all_by_ipo(C, ob->ipo)
435 return OPERATOR_CANCELLED;
437 else if (nr == OBJECT_SELECT_LINKED_OBDATA) {
439 return OPERATOR_CANCELLED;
441 changed = object_select_all_by_obdata(C, ob->data);
443 else if (nr == OBJECT_SELECT_LINKED_MATERIAL || nr == OBJECT_SELECT_LINKED_TEXTURE) {
444 Material *mat = NULL;
446 int use_texture = FALSE;
448 mat = give_current_material(ob, ob->actcol);
449 if (mat == NULL) return OPERATOR_CANCELLED;
450 if (nr == OBJECT_SELECT_LINKED_TEXTURE) {
453 if (mat->mtex[(int)mat->texact]) tex = mat->mtex[(int)mat->texact]->tex;
454 if (tex == NULL) return OPERATOR_CANCELLED;
457 changed = object_select_all_by_material_texture(C, use_texture, mat, tex);
459 else if (nr == OBJECT_SELECT_LINKED_DUPGROUP) {
460 if (ob->dup_group == NULL)
461 return OPERATOR_CANCELLED;
463 changed = object_select_all_by_dup_group(C, ob);
465 else if (nr == OBJECT_SELECT_LINKED_PARTICLE) {
466 if (ob->particlesystem.first == NULL)
467 return OPERATOR_CANCELLED;
469 changed = object_select_all_by_particle(C, ob);
471 else if (nr == OBJECT_SELECT_LINKED_LIBRARY) {
473 changed = object_select_all_by_library(C, ob->id.lib);
475 else if (nr == OBJECT_SELECT_LINKED_LIBRARY_OBDATA) {
476 if (ob->data == NULL)
477 return OPERATOR_CANCELLED;
479 changed = object_select_all_by_library_obdata(C, ((ID *) ob->data)->lib);
482 return OPERATOR_CANCELLED;
485 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
486 return OPERATOR_FINISHED;
489 return OPERATOR_CANCELLED;
492 void OBJECT_OT_select_linked(wmOperatorType *ot)
495 ot->name = "Select Linked";
496 ot->description = "Select all visible objects that are linked";
497 ot->idname = "OBJECT_OT_select_linked";
500 ot->invoke = WM_menu_invoke;
501 ot->exec = object_select_linked_exec;
502 ot->poll = objects_selectable_poll;
505 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
508 RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
509 ot->prop = RNA_def_enum(ot->srna, "type", prop_select_linked_types, 0, "Type", "");
512 /*********************** Selected Grouped ********************/
514 static EnumPropertyItem prop_select_grouped_types[] = {
515 {1, "CHILDREN_RECURSIVE", 0, "Children", ""},
516 {2, "CHILDREN", 0, "Immediate Children", ""},
517 {3, "PARENT", 0, "Parent", ""},
518 {4, "SIBLINGS", 0, "Siblings", "Shared Parent"},
519 {5, "TYPE", 0, "Type", "Shared object type"},
520 {6, "LAYER", 0, "Layer", "Shared layers"},
521 {7, "GROUP", 0, "Group", "Shared group"},
522 {8, "HOOK", 0, "Hook", ""},
523 {9, "PASS", 0, "Pass", "Render pass Index"},
524 {10, "COLOR", 0, "Color", "Object Color"},
525 {11, "PROPERTIES", 0, "Properties", "Game Properties"},
526 {12, "KEYINGSET", 0, "Keying Set", "Objects included in active Keying Set"},
527 {0, NULL, 0, NULL, NULL}
530 static short select_grouped_children(bContext *C, Object *ob, int recursive)
534 CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
536 if (ob == base->object->parent) {
537 if (!(base->flag & SELECT)) {
538 ED_base_object_select(base, BA_SELECT);
543 changed |= select_grouped_children(C, base->object, 1);
550 static short select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */
552 Scene *scene = CTX_data_scene(C);
553 View3D *v3d = CTX_wm_view3d(C);
556 Base *baspar, *basact = CTX_data_active_base(C);
558 if (!basact || !(basact->object->parent)) return 0; /* we know OBACT is valid */
560 baspar = BKE_scene_base_find(scene, basact->object->parent);
562 /* can be NULL if parent in other scene */
563 if (baspar && BASE_SELECTABLE(v3d, baspar)) {
564 ED_base_object_select(basact, BA_DESELECT);
565 ED_base_object_select(baspar, BA_SELECT);
566 ED_base_object_activate(C, baspar);
573 #define GROUP_MENU_MAX 24
574 static short select_grouped_group(bContext *C, Object *ob) /* Select objects in the same group as the active */
577 Group *group, *ob_groups[GROUP_MENU_MAX];
578 int group_count = 0, i;
582 for (group = CTX_data_main(C)->group.first; group && group_count < GROUP_MENU_MAX; group = group->id.next) {
583 if (object_in_group(ob, group)) {
584 ob_groups[group_count] = group;
591 else if (group_count == 1) {
592 group = ob_groups[0];
593 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
595 if (!(base->flag & SELECT) && object_in_group(base->object, group)) {
596 ED_base_object_select(base, BA_SELECT);
604 /* build the menu. */
605 pup = uiPupMenuBegin(C, "Select Group", ICON_NONE);
606 layout = uiPupMenuLayout(pup);
608 for (i = 0; i < group_count; i++) {
609 group = ob_groups[i];
610 uiItemStringO(layout, group->id.name + 2, 0, "OBJECT_OT_select_same_group", "group", group->id.name);
613 uiPupMenuEnd(C, pup);
614 return changed; // The operator already handle this!
617 static short select_grouped_object_hooks(bContext *C, Object *ob)
619 Scene *scene = CTX_data_scene(C);
620 View3D *v3d = CTX_wm_view3d(C);
625 HookModifierData *hmd;
627 for (md = ob->modifiers.first; md; md = md->next) {
628 if (md->type == eModifierType_Hook) {
629 hmd = (HookModifierData *) md;
630 if (hmd->object && !(hmd->object->flag & SELECT)) {
631 base = BKE_scene_base_find(scene, hmd->object);
632 if (base && (BASE_SELECTABLE(v3d, base))) {
633 ED_base_object_select(base, BA_SELECT);
642 /* Select objects with the same parent as the active (siblings),
643 * parent can be NULL also */
644 static short select_grouped_siblings(bContext *C, Object *ob)
648 CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
650 if ((base->object->parent == ob->parent) && !(base->flag & SELECT)) {
651 ED_base_object_select(base, BA_SELECT);
659 static short select_grouped_type(bContext *C, Object *ob)
663 CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
665 if ((base->object->type == ob->type) && !(base->flag & SELECT)) {
666 ED_base_object_select(base, BA_SELECT);
674 static short select_grouped_layer(bContext *C, Object *ob)
678 CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
680 if ((base->lay & ob->lay) && !(base->flag & SELECT)) {
681 ED_base_object_select(base, BA_SELECT);
689 static short select_grouped_index_object(bContext *C, Object *ob)
693 CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
695 if ((base->object->index == ob->index) && !(base->flag & SELECT)) {
696 ED_base_object_select(base, BA_SELECT);
704 static short select_grouped_color(bContext *C, Object *ob)
708 CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
710 if (!(base->flag & SELECT) && (compare_v3v3(base->object->col, ob->col, 0.005f))) {
711 ED_base_object_select(base, BA_SELECT);
719 static short objects_share_gameprop(Object *a, Object *b)
722 /*make a copy of all its properties*/
724 for (prop = a->prop.first; prop; prop = prop->next) {
725 if (get_ob_property(b, prop->name) )
731 static short select_grouped_gameprops(bContext *C, Object *ob)
735 CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
737 if (!(base->flag & SELECT) && (objects_share_gameprop(base->object, ob))) {
738 ED_base_object_select(base, BA_SELECT);
746 static short select_grouped_keyingset(bContext *C, Object *UNUSED(ob))
748 KeyingSet *ks = ANIM_scene_get_active_keyingset(CTX_data_scene(C));
751 /* firstly, validate KeyingSet */
752 if ((ks == NULL) || (ANIM_validate_keyingset(C, NULL, ks) != 0))
755 /* select each object that Keying Set refers to */
756 // TODO: perhaps to be more in line with the rest of these, we should only take objects
757 // if the passed in object is included in this too
758 CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
760 /* only check for this object if it isn't selected already, to limit time wasted */
761 if ((base->flag & SELECT) == 0) {
764 /* this is the slow way... we could end up with > 500 items here,
765 * with none matching, but end up doing this on 1000 objects...
767 for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
768 /* if id matches, select then stop looping (match found) */
769 if (ksp->id == (ID *)base->object) {
770 ED_base_object_select(base, BA_SELECT);
782 static int object_select_grouped_exec(bContext *C, wmOperator *op)
784 Scene *scene = CTX_data_scene(C);
786 int nr = RNA_enum_get(op->ptr, "type");
787 short changed = 0, extend;
789 extend = RNA_boolean_get(op->ptr, "extend");
792 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
794 ED_base_object_select(base, BA_DESELECT);
802 BKE_report(op->reports, RPT_ERROR, "No Active Object");
803 return OPERATOR_CANCELLED;
806 if (nr == 1) changed |= select_grouped_children(C, ob, 1);
807 else if (nr == 2) changed |= select_grouped_children(C, ob, 0);
808 else if (nr == 3) changed |= select_grouped_parent(C);
809 else if (nr == 4) changed |= select_grouped_siblings(C, ob);
810 else if (nr == 5) changed |= select_grouped_type(C, ob);
811 else if (nr == 6) changed |= select_grouped_layer(C, ob);
812 else if (nr == 7) changed |= select_grouped_group(C, ob);
813 else if (nr == 8) changed |= select_grouped_object_hooks(C, ob);
814 else if (nr == 9) changed |= select_grouped_index_object(C, ob);
815 else if (nr == 10) changed |= select_grouped_color(C, ob);
816 else if (nr == 11) changed |= select_grouped_gameprops(C, ob);
817 else if (nr == 12) changed |= select_grouped_keyingset(C, ob);
820 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
821 return OPERATOR_FINISHED;
824 return OPERATOR_CANCELLED;
827 void OBJECT_OT_select_grouped(wmOperatorType *ot)
830 ot->name = "Select Grouped";
831 ot->description = "Select all visible objects grouped by various properties";
832 ot->idname = "OBJECT_OT_select_grouped";
835 ot->invoke = WM_menu_invoke;
836 ot->exec = object_select_grouped_exec;
837 ot->poll = objects_selectable_poll;
840 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
843 RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
844 ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
847 /************************* Select by Layer **********************/
849 static int object_select_by_layer_exec(bContext *C, wmOperator *op)
851 unsigned int layernum;
854 extend = RNA_boolean_get(op->ptr, "extend");
855 layernum = RNA_int_get(op->ptr, "layers");
856 match = RNA_enum_get(op->ptr, "match");
859 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
861 ED_base_object_select(base, BA_DESELECT);
866 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
870 if (match == 1) /* exact */
871 ok = (base->lay == (1 << (layernum - 1)));
872 else /* shared layers */
873 ok = (base->lay & (1 << (layernum - 1)));
876 ED_base_object_select(base, BA_SELECT);
881 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
883 return OPERATOR_FINISHED;
886 void OBJECT_OT_select_by_layer(wmOperatorType *ot)
888 static EnumPropertyItem match_items[] = {
889 {1, "EXACT", 0, "Exact Match", ""},
890 {2, "SHARED", 0, "Shared Layers", ""},
891 {0, NULL, 0, NULL, NULL}
895 ot->name = "Select by Layer";
896 ot->description = "Select all visible objects on a layer";
897 ot->idname = "OBJECT_OT_select_by_layer";
900 /*ot->invoke = XXX - need a int grid popup*/
901 ot->exec = object_select_by_layer_exec;
902 ot->poll = objects_selectable_poll;
905 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
908 RNA_def_enum(ot->srna, "match", match_items, 0, "Match", "");
909 RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
910 RNA_def_int(ot->srna, "layers", 1, 1, 20, "Layer", "", 1, 20);
913 /**************************** (De)select All ****************************/
915 static int object_select_all_exec(bContext *C, wmOperator *op)
917 int action = RNA_enum_get(op->ptr, "action");
919 /* passthrough if no objects are visible */
920 if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH;
922 if (action == SEL_TOGGLE) {
924 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
926 if (base->flag & SELECT) {
927 action = SEL_DESELECT;
934 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
938 ED_base_object_select(base, BA_SELECT);
941 ED_base_object_select(base, BA_DESELECT);
944 if (base->flag & SELECT) {
945 ED_base_object_select(base, BA_DESELECT);
948 ED_base_object_select(base, BA_SELECT);
955 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
957 return OPERATOR_FINISHED;
960 void OBJECT_OT_select_all(wmOperatorType *ot)
964 ot->name = "(De)select All";
965 ot->description = "Change selection of all visible objects in scene";
966 ot->idname = "OBJECT_OT_select_all";
969 ot->exec = object_select_all_exec;
970 ot->poll = objects_selectable_poll;
973 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
975 WM_operator_properties_select_all(ot);
978 /**************************** Select In The Same Group ****************************/
980 static int object_select_same_group_exec(bContext *C, wmOperator *op)
983 char group_name[MAX_ID_NAME];
985 /* passthrough if no objects are visible */
986 if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH;
988 RNA_string_get(op->ptr, "group", group_name);
990 for (group = CTX_data_main(C)->group.first; group; group = group->id.next) {
991 if (!strcmp(group->id.name, group_name))
996 return OPERATOR_PASS_THROUGH;
998 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
1000 if (!(base->flag & SELECT) && object_in_group(base->object, group))
1001 ED_base_object_select(base, BA_SELECT);
1005 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
1007 return OPERATOR_FINISHED;
1010 void OBJECT_OT_select_same_group(wmOperatorType *ot)
1014 ot->name = "Select Same Group";
1015 ot->description = "Select object in the same group";
1016 ot->idname = "OBJECT_OT_select_same_group";
1019 ot->exec = object_select_same_group_exec;
1020 ot->poll = objects_selectable_poll;
1023 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1025 RNA_def_string(ot->srna, "group", "", MAX_ID_NAME, "Group", "Name of the group to select");
1028 /**************************** Select Mirror ****************************/
1029 static int object_select_mirror_exec(bContext *C, wmOperator *op)
1031 Scene *scene = CTX_data_scene(C);
1034 extend = RNA_boolean_get(op->ptr, "extend");
1036 CTX_DATA_BEGIN (C, Base *, primbase, selected_bases)
1038 char tmpname[MAXBONENAME];
1040 flip_side_name(tmpname, primbase->object->id.name + 2, TRUE);
1042 if (strcmp(tmpname, primbase->object->id.name + 2) != 0) { /* names differ */
1043 Object *ob = (Object *)BKE_libblock_find_name(ID_OB, tmpname);
1045 Base *secbase = BKE_scene_base_find(scene, ob);
1048 ED_base_object_select(secbase, BA_SELECT);
1053 if (extend == 0) ED_base_object_select(primbase, BA_DESELECT);
1059 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
1061 return OPERATOR_FINISHED;
1064 void OBJECT_OT_select_mirror(wmOperatorType *ot)
1068 ot->name = "Select Mirror";
1069 ot->description = "Select the Mirror objects of the selected object eg. L.sword -> R.sword";
1070 ot->idname = "OBJECT_OT_select_mirror";
1073 ot->exec = object_select_mirror_exec;
1074 ot->poll = objects_selectable_poll;
1077 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1079 RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first");
1083 /**************************** Select Random ****************************/
1085 static int object_select_random_exec(bContext *C, wmOperator *op)
1090 extend = RNA_boolean_get(op->ptr, "extend");
1093 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
1095 ED_base_object_select(base, BA_DESELECT);
1099 percent = RNA_float_get(op->ptr, "percent") / 100.0f;
1101 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
1103 if (BLI_frand() < percent) {
1104 ED_base_object_select(base, BA_SELECT);
1109 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
1111 return OPERATOR_FINISHED;
1114 void OBJECT_OT_select_random(wmOperatorType *ot)
1117 ot->name = "Select Random";
1118 ot->description = "Set select on random visible objects";
1119 ot->idname = "OBJECT_OT_select_random";
1122 /*ot->invoke = object_select_random_invoke XXX - need a number popup ;*/
1123 ot->exec = object_select_random_exec;
1124 ot->poll = objects_selectable_poll;
1127 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1130 RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of objects to select randomly", 0.f, 100.0f);
1131 RNA_def_boolean(ot->srna, "extend", FALSE, "Extend Selection", "Extend selection instead of deselecting everything first");