style cleanup: format 'for' loop macros the same as for loops, some renaming to BLI_a...
[blender.git] / source / blender / editors / object / object_select.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, 2002-2008 full recode
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/object/object_select.c
27  *  \ingroup edobj
28  */
29
30
31 #include <ctype.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "MEM_guardedalloc.h"
37
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"
45
46 #include "BLI_math.h"
47 #include "BLI_listbase.h"
48 #include "BLI_rand.h"
49 #include "BLI_string.h"
50 #include "BLI_utildefines.h"
51
52 #include "BKE_context.h"
53 #include "BKE_group.h"
54 #include "BKE_main.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"
62
63 #include "WM_api.h"
64 #include "WM_types.h"
65
66 #include "ED_object.h"
67 #include "ED_screen.h"
68 #include "ED_keyframing.h"
69
70 #include "UI_interface.h"
71 #include "UI_resources.h"
72
73 #include "RNA_access.h"
74 #include "RNA_define.h"
75 #include "RNA_enum_types.h"
76
77 #include "object_intern.h"
78
79 /************************ Exported **************************/
80
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 */
84
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 */
87
88 void ED_base_object_select(Base *base, short mode)
89 {
90         if (base) {
91                 if (mode==BA_SELECT) {
92                         if (!(base->object->restrictflag & OB_RESTRICT_SELECT))
93                                 base->flag |= SELECT;
94                 }
95                 else if (mode==BA_DESELECT) {
96                         base->flag &= ~SELECT;
97                 }
98                 base->object->flag= base->flag;
99         }
100 }
101
102 /* also to set active NULL */
103 void ED_base_object_activate(bContext *C, Base *base)
104 {
105         Scene *scene= CTX_data_scene(C);
106         
107         /* sets scene->basact */
108         BASACT= base;
109         
110         if (base) {
111                 
112                 /* XXX old signals, remember to handle notifiers now! */
113                 //              select_actionchannel_by_name(base->object->action, "Object", 1);
114                 
115                 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);
116         }
117         else
118                 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, NULL);
119 }
120
121 /********************** Selection Operators **********************/
122
123 static int objects_selectable_poll(bContext *C)
124 {
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);
128
129         if (CTX_data_edit_object(C))
130                 return 0;
131         if (obact && obact->mode)
132                 return 0;
133         
134         return 1;
135 }
136
137 /************************ Select by Type *************************/
138
139 static int object_select_by_type_exec(bContext *C, wmOperator *op)
140 {
141         short obtype, extend;
142         
143         obtype = RNA_enum_get(op->ptr, "type");
144         extend= RNA_boolean_get(op->ptr, "extend");
145                 
146         if (extend == 0) {
147                 CTX_DATA_BEGIN (C, Base*, base, visible_bases) {
148                         ED_base_object_select(base, BA_DESELECT);
149                 }
150                 CTX_DATA_END;
151         }
152         
153         CTX_DATA_BEGIN (C, Base*, base, visible_bases) {
154                 if (base->object->type==obtype) {
155                         ED_base_object_select(base, BA_SELECT);
156                 }
157         }
158         CTX_DATA_END;
159         
160         WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
161         
162         return OPERATOR_FINISHED;
163 }
164
165 void OBJECT_OT_select_by_type(wmOperatorType *ot)
166 {
167         /* identifiers */
168         ot->name = "Select By Type";
169         ot->description = "Select all visible objects that are of a type";
170         ot->idname = "OBJECT_OT_select_by_type";
171         
172         /* api callbacks */
173         ot->invoke = WM_menu_invoke;
174         ot->exec = object_select_by_type_exec;
175         ot->poll = objects_selectable_poll;
176         
177         /* flags */
178         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
179         
180         /* properties */
181         RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
182         ot->prop = RNA_def_enum(ot->srna, "type", object_type_items, 1, "Type", "");
183 }
184
185 /*********************** Selection by Links *********************/
186
187 static EnumPropertyItem prop_select_linked_types[] = {
188         //{1, "IPO", 0, "Object IPO", ""}, // XXX depreceated animation system stuff...
189         {2, "OBDATA", 0, "Object Data", ""},
190         {3, "MATERIAL", 0, "Material", ""},
191         {4, "TEXTURE", 0, "Texture", ""},
192         {5, "DUPGROUP", 0, "Dupligroup", ""},
193         {6, "PARTICLE", 0, "Particle System", ""},
194         {7, "LIBRARY", 0, "Library", ""},
195         {8, "LIBRARY_OBDATA", 0, "Library (Object Data)", ""},
196         {0, NULL, 0, NULL, NULL}
197 };
198
199 static int object_select_linked_exec(bContext *C, wmOperator *op)
200 {
201         Scene *scene= CTX_data_scene(C);
202         Object *ob;
203         void *obdata = NULL;
204         Material *mat = NULL, *mat1;
205         Tex *tex= NULL;
206         int a, b;
207         int nr = RNA_enum_get(op->ptr, "type");
208         short changed = 0, extend;
209         /* events (nr):
210          * Object Ipo: 1
211          * ObData: 2
212          * Current Material: 3
213          * Current Texture: 4
214          * DupliGroup: 5
215          * PSys: 6
216          */
217
218         extend= RNA_boolean_get(op->ptr, "extend");
219         
220         if (extend == 0) {
221                 CTX_DATA_BEGIN (C, Base*, base, visible_bases) {
222                         ED_base_object_select(base, BA_DESELECT);
223                 }
224                 CTX_DATA_END;
225         }
226         
227         ob= OBACT;
228         if (ob==NULL) { 
229                 BKE_report(op->reports, RPT_ERROR, "No Active Object");
230                 return OPERATOR_CANCELLED;
231         }
232         
233         if (nr==1) {    
234                         // XXX old animation system
235                 //ipo= ob->ipo;
236                 //if (ipo==0) return OPERATOR_CANCELLED;
237                 return OPERATOR_CANCELLED;
238         }
239         else if (nr==2) {
240                 if (ob->data==NULL) return OPERATOR_CANCELLED;
241                 obdata= ob->data;
242         }
243         else if (nr==3 || nr==4) {
244                 mat= give_current_material(ob, ob->actcol);
245                 if (mat==NULL) return OPERATOR_CANCELLED;
246                 if (nr==4) {
247                         if (mat->mtex[ (int)mat->texact ]) tex= mat->mtex[ (int)mat->texact ]->tex;
248                         if (tex==NULL) return OPERATOR_CANCELLED;
249                 }
250         }
251         else if (nr==5) {
252                 if (ob->dup_group==NULL) return OPERATOR_CANCELLED;
253         }
254         else if (nr==6) {
255                 if (ob->particlesystem.first==NULL) return OPERATOR_CANCELLED;
256         }
257         else if (nr==7) {
258                 /* do nothing */
259         }
260         else if (nr==8) {
261                 if (ob->data==NULL) return OPERATOR_CANCELLED;
262         }
263         else
264                 return OPERATOR_CANCELLED;
265         
266         CTX_DATA_BEGIN (C, Base*, base, visible_bases) {
267                 if (nr==1) {
268                                 // XXX old animation system
269                         //if (base->object->ipo==ipo) base->flag |= SELECT;
270                         //changed = 1;
271                 }
272                 else if (nr==2) {
273                         if (base->object->data==obdata) base->flag |= SELECT;
274                         changed = 1;
275                 }
276                 else if (nr==3 || nr==4) {
277                         ob= base->object;
278                         
279                         for (a=1; a<=ob->totcol; a++) {
280                                 mat1= give_current_material(ob, a);
281                                 if (nr==3) {
282                                         if (mat1==mat) base->flag |= SELECT;
283                                         changed = 1;
284                                 }
285                                 else if (mat1 && nr==4) {
286                                         for (b=0; b<MAX_MTEX; b++) {
287                                                 if (mat1->mtex[b]) {
288                                                         if (tex==mat1->mtex[b]->tex) {
289                                                                 base->flag |= SELECT;
290                                                                 changed = 1;
291                                                                 break;
292                                                         }
293                                                 }
294                                         }
295                                 }
296                         }
297                 }
298                 else if (nr==5) {
299                         if (base->object->dup_group==ob->dup_group) {
300                                 base->flag |= SELECT;
301                                 changed = 1;
302                         }
303                 }
304                 else if (nr==6) {
305                         /* loop through other, then actives particles*/
306                         ParticleSystem *psys;
307                         ParticleSystem *psys_act;
308                         
309                         for (psys=base->object->particlesystem.first; psys; psys=psys->next) {
310                                 for (psys_act=ob->particlesystem.first; psys_act; psys_act=psys_act->next) {
311                                         if (psys->part == psys_act->part) {
312                                                 base->flag |= SELECT;
313                                                 changed = 1;
314                                                 break;
315                                         }
316                                 }
317                                 
318                                 if (base->flag & SELECT) {
319                                         break;
320                                 }
321                         }
322                 }
323                 else if (nr==7) {
324                         if (ob->id.lib == base->object->id.lib) {
325                                 base->flag |= SELECT;
326                                 changed= 1;
327                         }
328                 }
329                 else if (nr==8) {
330                         if (base->object->data && ((ID *)ob->data)->lib == ((ID *)base->object->data)->lib) {
331                                 base->flag |= SELECT;
332                                 changed= 1;
333                         }
334                 }
335                 base->object->flag= base->flag;
336         }
337         CTX_DATA_END;
338         
339         if (changed) {
340                 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
341                 return OPERATOR_FINISHED;
342         }
343         
344         return OPERATOR_CANCELLED;
345 }
346
347 void OBJECT_OT_select_linked(wmOperatorType *ot)
348 {
349         /* identifiers */
350         ot->name = "Select Linked";
351         ot->description = "Select all visible objects that are linked";
352         ot->idname = "OBJECT_OT_select_linked";
353         
354         /* api callbacks */
355         ot->invoke = WM_menu_invoke;
356         ot->exec = object_select_linked_exec;
357         ot->poll = objects_selectable_poll;
358         
359         /* flags */
360         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
361         
362         /* properties */
363         RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
364         ot->prop = RNA_def_enum(ot->srna, "type", prop_select_linked_types, 0, "Type", "");
365 }
366
367 /*********************** Selected Grouped ********************/
368
369 static EnumPropertyItem prop_select_grouped_types[] = {
370         {1, "CHILDREN_RECURSIVE", 0, "Children", ""},
371         {2, "CHILDREN", 0, "Immediate Children", ""},
372         {3, "PARENT", 0, "Parent", ""},
373         {4, "SIBLINGS", 0, "Siblings", "Shared Parent"},
374         {5, "TYPE", 0, "Type", "Shared object type"},
375         {6, "LAYER", 0, "Layer", "Shared layers"},
376         {7, "GROUP", 0, "Group", "Shared group"},
377         {8, "HOOK", 0, "Hook", ""},
378         {9, "PASS", 0, "Pass", "Render pass Index"},
379         {10, "COLOR", 0, "Color", "Object Color"},
380         {11, "PROPERTIES", 0, "Properties", "Game Properties"},
381         {12, "KEYINGSET", 0, "Keying Set", "Objects included in active Keying Set"},
382         {0, NULL, 0, NULL, NULL}
383 };
384
385 static short select_grouped_children(bContext *C, Object *ob, int recursive)
386 {
387         short changed = 0;
388
389         CTX_DATA_BEGIN (C, Base*, base, selectable_bases) {
390                 if (ob == base->object->parent) {
391                         if (!(base->flag & SELECT)) {
392                                 ED_base_object_select(base, BA_SELECT);
393                                 changed = 1;
394                         }
395
396                         if (recursive)
397                                 changed |= select_grouped_children(C, base->object, 1);
398                 }
399         }
400         CTX_DATA_END;
401         return changed;
402 }
403
404 static short select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */
405 {
406         Scene *scene= CTX_data_scene(C);
407         View3D *v3d= CTX_wm_view3d(C);
408
409         short changed = 0;
410         Base *baspar, *basact= CTX_data_active_base(C);
411
412         if (!basact || !(basact->object->parent)) return 0; /* we know OBACT is valid */
413
414         baspar= object_in_scene(basact->object->parent, scene);
415
416         /* can be NULL if parent in other scene */
417         if (baspar && BASE_SELECTABLE(v3d, baspar)) {
418                 ED_base_object_select(basact, BA_DESELECT);
419                 ED_base_object_select(baspar, BA_SELECT);
420                 ED_base_object_activate(C, baspar);
421                 changed = 1;
422         }
423         return changed;
424 }
425
426
427 #define GROUP_MENU_MAX  24
428 static short select_grouped_group(bContext *C, Object *ob)      /* Select objects in the same group as the active */
429 {
430         short changed = 0;
431         Group *group, *ob_groups[GROUP_MENU_MAX];
432         int group_count=0, i;
433         uiPopupMenu *pup;
434         uiLayout *layout;
435
436         for (group=CTX_data_main(C)->group.first; group && group_count < GROUP_MENU_MAX; group=group->id.next) {
437                 if (object_in_group (ob, group)) {
438                         ob_groups[group_count] = group;
439                         group_count++;
440                 }
441         }
442
443         if (!group_count)
444                 return 0;
445         else if (group_count == 1) {
446                 group = ob_groups[0];
447                 CTX_DATA_BEGIN (C, Base*, base, visible_bases) {
448                         if (!(base->flag & SELECT) && object_in_group(base->object, group)) {
449                                 ED_base_object_select(base, BA_SELECT);
450                                 changed = 1;
451                         }
452                 }
453                 CTX_DATA_END;
454                 return changed;
455         }
456
457         /* build the menu. */
458         pup= uiPupMenuBegin(C, "Select Group", ICON_NONE);
459         layout= uiPupMenuLayout(pup);
460
461         for (i=0; i<group_count; i++) {
462                 group = ob_groups[i];
463                 uiItemStringO(layout, group->id.name+2, 0, "OBJECT_OT_select_same_group", "group", group->id.name);
464         }
465
466         uiPupMenuEnd(C, pup);
467         return changed; // The operator already handle this!
468 }
469
470 static short select_grouped_object_hooks(bContext *C, Object *ob)
471 {
472         Scene *scene= CTX_data_scene(C);
473         View3D *v3d= CTX_wm_view3d(C);
474
475         short changed = 0;
476         Base *base;
477         ModifierData *md;
478         HookModifierData *hmd;
479
480         for (md = ob->modifiers.first; md; md=md->next) {
481                 if (md->type==eModifierType_Hook) {
482                         hmd= (HookModifierData*) md;
483                         if (hmd->object && !(hmd->object->flag & SELECT)) {
484                                 base= object_in_scene(hmd->object, scene);
485                                 if (base && (BASE_SELECTABLE(v3d, base))) {
486                                         ED_base_object_select(base, BA_SELECT);
487                                         changed = 1;
488                                 }
489                         }
490                 }
491         }
492         return changed;
493 }
494
495 /* Select objects with the same parent as the active (siblings),
496  * parent can be NULL also */
497 static short select_grouped_siblings(bContext *C, Object *ob)
498 {
499         short changed = 0;
500
501         CTX_DATA_BEGIN (C, Base*, base, selectable_bases) {
502                 if ((base->object->parent==ob->parent)  && !(base->flag & SELECT)) {
503                         ED_base_object_select(base, BA_SELECT);
504                         changed = 1;
505                 }
506         }
507         CTX_DATA_END;
508         return changed;
509 }
510
511 static short select_grouped_type(bContext *C, Object *ob)
512 {
513         short changed = 0;
514
515         CTX_DATA_BEGIN (C, Base*, base, selectable_bases) {
516                 if ((base->object->type == ob->type) && !(base->flag & SELECT)) {
517                         ED_base_object_select(base, BA_SELECT);
518                         changed = 1;
519                 }
520         }
521         CTX_DATA_END;
522         return changed;
523 }
524
525 static short select_grouped_layer(bContext *C, Object *ob)
526 {
527         char changed = 0;
528
529         CTX_DATA_BEGIN (C, Base*, base, selectable_bases) {
530                 if ((base->lay & ob->lay) && !(base->flag & SELECT)) {
531                         ED_base_object_select(base, BA_SELECT);
532                         changed = 1;
533                 }
534         }
535         CTX_DATA_END;
536         return changed;
537 }
538
539 static short select_grouped_index_object(bContext *C, Object *ob)
540 {
541         char changed = 0;
542
543         CTX_DATA_BEGIN (C, Base*, base, selectable_bases) {
544                 if ((base->object->index == ob->index) && !(base->flag & SELECT)) {
545                         ED_base_object_select(base, BA_SELECT);
546                         changed = 1;
547                 }
548         }
549         CTX_DATA_END;
550         return changed;
551 }
552
553 static short select_grouped_color(bContext *C, Object *ob)
554 {
555         char changed = 0;
556
557         CTX_DATA_BEGIN (C, Base*, base, selectable_bases) {
558                 if (!(base->flag & SELECT) && (compare_v3v3(base->object->col, ob->col, 0.005f))) {
559                         ED_base_object_select(base, BA_SELECT);
560                         changed = 1;
561                 }
562         }
563         CTX_DATA_END;
564         return changed;
565 }
566
567 static short objects_share_gameprop(Object *a, Object *b)
568 {
569         bProperty *prop;
570         /*make a copy of all its properties*/
571
572         for ( prop= a->prop.first; prop; prop = prop->next ) {
573                 if ( get_ob_property(b, prop->name) )
574                         return 1;
575         }
576         return 0;
577 }
578
579 static short select_grouped_gameprops(bContext *C, Object *ob)
580 {
581         char changed = 0;
582
583         CTX_DATA_BEGIN (C, Base*, base, selectable_bases) {
584                 if (!(base->flag & SELECT) && (objects_share_gameprop(base->object, ob))) {
585                         ED_base_object_select(base, BA_SELECT);
586                         changed = 1;
587                 }
588         }
589         CTX_DATA_END;
590         return changed;
591 }
592
593 static short select_grouped_keyingset(bContext *C, Object *UNUSED(ob))
594 {
595         KeyingSet *ks = ANIM_scene_get_active_keyingset(CTX_data_scene(C));
596         short changed = 0;
597         
598         /* firstly, validate KeyingSet */
599         if ((ks == NULL) || (ANIM_validate_keyingset(C, NULL, ks) != 0))
600                 return 0;
601         
602         /* select each object that Keying Set refers to */
603         // TODO: perhaps to be more in line with the rest of these, we should only take objects 
604         // if the passed in object is included in this too
605         CTX_DATA_BEGIN (C, Base*, base, selectable_bases) {
606                 /* only check for this object if it isn't selected already, to limit time wasted */
607                 if ((base->flag & SELECT) == 0) {
608                         KS_Path *ksp;
609                         
610                         /* this is the slow way... we could end up with > 500 items here, 
611                          * with none matching, but end up doing this on 1000 objects...
612                          */
613                         for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
614                                 /* if id matches, select then stop looping (match found) */
615                                 if (ksp->id == (ID *)base->object) {
616                                         ED_base_object_select(base, BA_SELECT);
617                                         changed = 1;
618                                         break;
619                                 }
620                         }
621                 }
622         }
623         CTX_DATA_END;
624                 
625         return changed;
626 }
627
628 static int object_select_grouped_exec(bContext *C, wmOperator *op)
629 {
630         Scene *scene= CTX_data_scene(C);
631         Object *ob;
632         int nr = RNA_enum_get(op->ptr, "type");
633         short changed = 0, extend;
634
635         extend= RNA_boolean_get(op->ptr, "extend");
636         
637         if (extend == 0) {
638                 CTX_DATA_BEGIN (C, Base*, base, visible_bases) {
639                         ED_base_object_select(base, BA_DESELECT);
640                         changed = 1;
641                 }
642                 CTX_DATA_END;
643         }
644         
645         ob= OBACT;
646         if (ob==NULL) { 
647                 BKE_report(op->reports, RPT_ERROR, "No Active Object");
648                 return OPERATOR_CANCELLED;
649         }
650         
651         if (nr==1)              changed |= select_grouped_children(C, ob, 1);
652         else if (nr==2) changed |= select_grouped_children(C, ob, 0);
653         else if (nr==3) changed |= select_grouped_parent(C);
654         else if (nr==4) changed |= select_grouped_siblings(C, ob);
655         else if (nr==5) changed |= select_grouped_type(C, ob);
656         else if (nr==6) changed |= select_grouped_layer(C, ob);
657         else if (nr==7) changed |= select_grouped_group(C, ob);
658         else if (nr==8) changed |= select_grouped_object_hooks(C, ob);
659         else if (nr==9) changed |= select_grouped_index_object(C, ob);
660         else if (nr==10)        changed |= select_grouped_color(C, ob);
661         else if (nr==11)        changed |= select_grouped_gameprops(C, ob);
662         else if (nr==12) changed |= select_grouped_keyingset(C, ob);
663         
664         if (changed) {
665                 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
666                 return OPERATOR_FINISHED;
667         }
668         
669         return OPERATOR_CANCELLED;
670 }
671
672 void OBJECT_OT_select_grouped(wmOperatorType *ot)
673 {
674         /* identifiers */
675         ot->name = "Select Grouped";
676         ot->description = "Select all visible objects grouped by various properties";
677         ot->idname = "OBJECT_OT_select_grouped";
678         
679         /* api callbacks */
680         ot->invoke = WM_menu_invoke;
681         ot->exec = object_select_grouped_exec;
682         ot->poll = objects_selectable_poll;
683         
684         /* flags */
685         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
686         
687         /* properties */
688         RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
689         ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
690 }
691
692 /************************* Select by Layer **********************/
693
694 static int object_select_by_layer_exec(bContext *C, wmOperator *op)
695 {
696         unsigned int layernum;
697         short extend;
698         
699         extend= RNA_boolean_get(op->ptr, "extend");
700         layernum = RNA_int_get(op->ptr, "layers");
701         
702         if (extend == 0) {
703                 CTX_DATA_BEGIN (C, Base*, base, visible_bases) {
704                         ED_base_object_select(base, BA_DESELECT);
705                 }
706                 CTX_DATA_END;
707         }
708                 
709         CTX_DATA_BEGIN (C, Base*, base, visible_bases) {
710                 if (base->lay == (1<< (layernum -1)))
711                         ED_base_object_select(base, BA_SELECT);
712         }
713         CTX_DATA_END;
714         
715         /* undo? */
716         WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
717         
718         return OPERATOR_FINISHED;
719 }
720
721 void OBJECT_OT_select_by_layer(wmOperatorType *ot)
722 {
723         /* identifiers */
724         ot->name = "Select by Layer";
725         ot->description = "Select all visible objects on a layer";
726         ot->idname = "OBJECT_OT_select_by_layer";
727         
728         /* api callbacks */
729         /*ot->invoke = XXX - need a int grid popup*/
730         ot->exec = object_select_by_layer_exec;
731         ot->poll = objects_selectable_poll;
732         
733         /* flags */
734         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
735         
736         /* properties */
737         RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
738         RNA_def_int(ot->srna, "layers", 1, 1, 20, "Layer", "", 1, 20);
739 }
740
741 /**************************** (De)select All ****************************/
742
743 static int object_select_all_exec(bContext *C, wmOperator *op)
744 {
745         int action = RNA_enum_get(op->ptr, "action");
746         
747         /* passthrough if no objects are visible */
748         if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH;
749
750         if (action == SEL_TOGGLE) {
751                 action = SEL_SELECT;
752                 CTX_DATA_BEGIN (C, Base*, base, visible_bases) {
753                         if (base->flag & SELECT) {
754                                 action = SEL_DESELECT;
755                                 break;
756                         }
757                 }
758                 CTX_DATA_END;
759         }
760
761         CTX_DATA_BEGIN (C, Base*, base, visible_bases) {
762                 switch (action) {
763                 case SEL_SELECT:
764                         ED_base_object_select(base, BA_SELECT);
765                         break;
766                 case SEL_DESELECT:
767                         ED_base_object_select(base, BA_DESELECT);
768                         break;
769                 case SEL_INVERT:
770                         if (base->flag & SELECT) {
771                                 ED_base_object_select(base, BA_DESELECT);
772                         }
773                         else {
774                                 ED_base_object_select(base, BA_SELECT);
775                         }
776                         break;
777                 }
778         }
779         CTX_DATA_END;
780         
781         WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
782         
783         return OPERATOR_FINISHED;
784 }
785
786 void OBJECT_OT_select_all(wmOperatorType *ot)
787 {
788         
789         /* identifiers */
790         ot->name = "(De)select All";
791         ot->description = "Change selection of all visible objects in scene";
792         ot->idname = "OBJECT_OT_select_all";
793         
794         /* api callbacks */
795         ot->exec = object_select_all_exec;
796         ot->poll = objects_selectable_poll;
797         
798         /* flags */
799         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
800
801         WM_operator_properties_select_all(ot);
802 }
803
804 /**************************** Select In The Same Group ****************************/
805
806 static int object_select_same_group_exec(bContext *C, wmOperator *op)
807 {
808         Group *group;
809         char group_name[MAX_ID_NAME];
810
811         /* passthrough if no objects are visible */
812         if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH;
813
814         RNA_string_get(op->ptr, "group", group_name);
815
816         for (group=CTX_data_main(C)->group.first;       group; group=group->id.next) {
817                 if (!strcmp(group->id.name, group_name))
818                         break;
819         }
820
821         if (!group)
822                 return OPERATOR_PASS_THROUGH;
823
824         CTX_DATA_BEGIN (C, Base*, base, visible_bases) {
825                 if (!(base->flag & SELECT) && object_in_group(base->object, group))
826                         ED_base_object_select(base, BA_SELECT);
827         }
828         CTX_DATA_END;
829
830         WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
831         
832         return OPERATOR_FINISHED;
833 }
834
835 void OBJECT_OT_select_same_group(wmOperatorType *ot)
836 {
837         
838         /* identifiers */
839         ot->name = "Select Same Group";
840         ot->description = "Select object in the same group";
841         ot->idname = "OBJECT_OT_select_same_group";
842         
843         /* api callbacks */
844         ot->exec = object_select_same_group_exec;
845         ot->poll = objects_selectable_poll;
846         
847         /* flags */
848         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
849
850         RNA_def_string(ot->srna, "group", "", MAX_ID_NAME, "Group", "Name of the group to select");
851 }
852
853 /**************************** Select Mirror ****************************/
854 static int object_select_mirror_exec(bContext *C, wmOperator *op)
855 {
856         Scene *scene= CTX_data_scene(C);
857         short extend;
858         
859         extend= RNA_boolean_get(op->ptr, "extend");
860         
861         CTX_DATA_BEGIN (C, Base*, primbase, selected_bases) {
862                 char tmpname[MAXBONENAME];
863
864                 flip_side_name(tmpname, primbase->object->id.name+2, TRUE);
865                 
866                 if (strcmp(tmpname, primbase->object->id.name+2)!=0) { /* names differ */
867                         Object *ob= (Object *)find_id("OB", tmpname);
868                         if (ob) {
869                                 Base *secbase= object_in_scene(ob, scene);
870
871                                 if (secbase) {
872                                         ED_base_object_select(secbase, BA_SELECT);
873                                 }
874                         }
875                 }
876                 
877                 if (extend == 0) ED_base_object_select(primbase, BA_DESELECT);
878                 
879         }
880         CTX_DATA_END;
881         
882         /* undo? */
883         WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
884         
885         return OPERATOR_FINISHED;
886 }
887
888 void OBJECT_OT_select_mirror(wmOperatorType *ot)
889 {
890         
891         /* identifiers */
892         ot->name = "Select Mirror";
893         ot->description = "Select the Mirror objects of the selected object eg. L.sword -> R.sword";
894         ot->idname = "OBJECT_OT_select_mirror";
895         
896         /* api callbacks */
897         ot->exec = object_select_mirror_exec;
898         ot->poll = objects_selectable_poll;
899         
900         /* flags */
901         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
902         
903         RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first");
904 }
905
906
907 /**************************** Select Random ****************************/
908
909 static int object_select_random_exec(bContext *C, wmOperator *op)
910 {       
911         float percent;
912         short extend;
913         
914         extend= RNA_boolean_get(op->ptr, "extend");
915         
916         if (extend == 0) {
917                 CTX_DATA_BEGIN (C, Base*, base, visible_bases) {
918                         ED_base_object_select(base, BA_DESELECT);
919                 }
920                 CTX_DATA_END;
921         }
922         percent = RNA_float_get(op->ptr, "percent")/100.0f;
923                 
924         CTX_DATA_BEGIN (C, Base*, base, visible_bases) {
925                 if (BLI_frand() < percent) {
926                         ED_base_object_select(base, BA_SELECT);
927                 }
928         }
929         CTX_DATA_END;
930         
931         WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
932         
933         return OPERATOR_FINISHED;
934 }
935
936 void OBJECT_OT_select_random(wmOperatorType *ot)
937 {
938         /* identifiers */
939         ot->name = "Select Random";
940         ot->description = "Set select on random visible objects";
941         ot->idname = "OBJECT_OT_select_random";
942         
943         /* api callbacks */
944         /*ot->invoke = object_select_random_invoke XXX - need a number popup ;*/
945         ot->exec = object_select_random_exec;
946         ot->poll = objects_selectable_poll;
947         
948         /* flags */
949         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
950         
951         /* properties */
952         RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of objects to select randomly", 0.f, 100.0f);
953         RNA_def_boolean(ot->srna, "extend", FALSE, "Extend Selection", "Extend selection instead of deselecting everything first");
954 }
955
956