5eab16cd7276abe40dbfb75b2d80c388400c336a
[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 "DNA_anim_types.h"
37 #include "DNA_group_types.h"
38 #include "DNA_material_types.h"
39 #include "DNA_modifier_types.h"
40 #include "DNA_property_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_armature_types.h"
43 #include "DNA_lamp_types.h"
44 #include "DNA_workspace_types.h"
45
46 #include "BLI_math.h"
47 #include "BLI_listbase.h"
48 #include "BLI_rand.h"
49 #include "BLI_string_utils.h"
50 #include "BLI_utildefines.h"
51
52 #include "BLT_translation.h"
53
54 #include "BKE_context.h"
55 #include "BKE_group.h"
56 #include "BKE_layer.h"
57 #include "BKE_main.h"
58 #include "BKE_material.h"
59 #include "BKE_object.h"
60 #include "BKE_particle.h"
61 #include "BKE_paint.h"
62 #include "BKE_property.h"
63 #include "BKE_report.h"
64 #include "BKE_scene.h"
65 #include "BKE_workspace.h"
66 #include "BKE_library.h"
67 #include "BKE_deform.h"
68
69 #include "DEG_depsgraph.h"
70
71 #include "WM_api.h"
72 #include "WM_types.h"
73
74 #include "ED_object.h"
75 #include "ED_screen.h"
76 #include "ED_keyframing.h"
77
78 #include "UI_interface.h"
79 #include "UI_resources.h"
80
81 #include "RNA_access.h"
82 #include "RNA_define.h"
83 #include "RNA_enum_types.h"
84
85 #include "object_intern.h"
86
87 /************************ Exported **************************/
88
89 /* simple API for object selection, rather than just using the flag
90  * this takes into account the 'restrict selection in 3d view' flag.
91  * deselect works always, the restriction just prevents selection */
92
93 /* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! (or 
94  * or a NC_SCENE|ND_OB_VISIBLE in case of visibility toggling */
95
96 void ED_object_base_select(Base *base, eObjectSelect_Mode mode)
97 {
98         if (mode == BA_INVERT) {
99                 mode = (base->flag & BASE_SELECTED) != 0 ? BA_DESELECT : BA_SELECT;
100         }
101
102         if (base) {
103                 switch (mode) {
104                         case BA_SELECT:
105                                 if ((base->flag & BASE_SELECTABLED) != 0) {
106                                         base->flag |= BASE_SELECTED;
107                                 }
108                                 break;
109                         case BA_DESELECT:
110                                 base->flag &= ~BASE_SELECTED;
111                                 break;
112                         case BA_INVERT:
113                                 /* Never happens. */
114                                 break;
115                 }
116                 BKE_scene_object_base_flag_sync_from_base(base);
117         }
118 }
119
120 /**
121  * Change active base, it includes the notifier
122  */
123 void ED_object_base_activate(bContext *C, Base *base)
124 {
125         ViewLayer *view_layer = CTX_data_view_layer(C);
126
127         WorkSpace *workspace = CTX_wm_workspace(C);
128
129         eObjectMode object_mode = workspace->object_mode;
130         eObjectMode object_mode_set = OB_MODE_OBJECT;
131
132         if (base && ED_workspace_object_mode_in_other_window(
133                     CTX_wm_manager(C), workspace, base->object,
134                     &object_mode_set))
135         {
136                 /* Sync existing object mode with workspace. */
137                 workspace->object_mode = object_mode_set;
138         }
139         else {
140                 /* Apply the workspaces more to the object (when possible). */
141                 bool reset = true;
142                 if (base) {
143                         Object *ob_prev = OBACT(view_layer);
144                         Object *ob_curr = base->object;
145                         if (ob_prev != NULL) {
146                                 if (ob_prev->type == ob_curr->type) {
147                                         reset = false;
148                                 }
149                         }
150                 }
151
152                 Scene *scene = CTX_data_scene(C);
153                 Object *obact = base ? base->object : NULL;
154                 /* We don't know the previous active object in update.
155                  *
156                  * Not correct because it's possible other work-spaces use these.
157                  * although that's a corner case. */
158                 if (workspace->object_mode & OB_MODE_ALL_MODE_DATA) {
159                         EvaluationContext eval_ctx;
160                         CTX_data_eval_ctx(C, &eval_ctx);
161                         FOREACH_OBJECT(view_layer, ob) {
162                                 if (ob != obact) {
163                                         ED_object_mode_generic_exit(&eval_ctx, workspace, scene, ob);
164                                 }
165                         }
166                         FOREACH_OBJECT_END;
167                 }
168
169                 workspace->object_mode = OB_MODE_OBJECT;
170
171                 view_layer->basact = base;
172
173                 if (reset == false) {
174                         ED_object_mode_generic_enter(C, object_mode);
175                 }
176         }
177
178         if (base) {
179                 WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, view_layer);
180         }
181         else {
182                 WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, NULL);
183         }
184 }
185
186 /********************** Selection Operators **********************/
187
188 static int objects_selectable_poll(bContext *C)
189 {
190         /* we don't check for linked scenes here, selection is
191          * still allowed then for inspection of scene */
192         if (CTX_data_edit_object(C)) {
193                 return 0;
194         }
195
196         const WorkSpace *workspace = CTX_wm_workspace(C);
197         if (workspace->object_mode != OB_MODE_OBJECT) {
198                 return 0;
199         }
200         return 1;
201 }
202
203 /************************ Select by Type *************************/
204
205 static int object_select_by_type_exec(bContext *C, wmOperator *op)
206 {
207         short obtype, extend;
208         
209         obtype = RNA_enum_get(op->ptr, "type");
210         extend = RNA_boolean_get(op->ptr, "extend");
211                 
212         if (extend == 0) {
213                 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
214                 {
215                         ED_object_base_select(base, BA_DESELECT);
216                 }
217                 CTX_DATA_END;
218         }
219         
220         CTX_DATA_BEGIN (C, Base *, base, visible_bases)
221         {
222                 if (base->object->type == obtype) {
223                         ED_object_base_select(base, BA_SELECT);
224                 }
225         }
226         CTX_DATA_END;
227         
228         WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
229         
230         return OPERATOR_FINISHED;
231 }
232
233 void OBJECT_OT_select_by_type(wmOperatorType *ot)
234 {
235         /* identifiers */
236         ot->name = "Select By Type";
237         ot->description = "Select all visible objects that are of a type";
238         ot->idname = "OBJECT_OT_select_by_type";
239         
240         /* api callbacks */
241         ot->invoke = WM_menu_invoke;
242         ot->exec = object_select_by_type_exec;
243         ot->poll = objects_selectable_poll;
244         
245         /* flags */
246         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
247         
248         /* properties */
249         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
250         ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_type_items, 1, "Type", "");
251 }
252
253 /*********************** Selection by Links *********************/
254
255 enum {
256         OBJECT_SELECT_LINKED_IPO = 1,
257         OBJECT_SELECT_LINKED_OBDATA,
258         OBJECT_SELECT_LINKED_MATERIAL,
259         OBJECT_SELECT_LINKED_TEXTURE,
260         OBJECT_SELECT_LINKED_DUPGROUP,
261         OBJECT_SELECT_LINKED_PARTICLE,
262         OBJECT_SELECT_LINKED_LIBRARY,
263         OBJECT_SELECT_LINKED_LIBRARY_OBDATA
264 };
265
266 static const EnumPropertyItem prop_select_linked_types[] = {
267         //{OBJECT_SELECT_LINKED_IPO, "IPO", 0, "Object IPO", ""}, // XXX deprecated animation system stuff...
268         {OBJECT_SELECT_LINKED_OBDATA, "OBDATA", 0, "Object Data", ""},
269         {OBJECT_SELECT_LINKED_MATERIAL, "MATERIAL", 0, "Material", ""},
270         {OBJECT_SELECT_LINKED_TEXTURE, "TEXTURE", 0, "Texture", ""},
271         {OBJECT_SELECT_LINKED_DUPGROUP, "DUPGROUP", 0, "Dupligroup", ""},
272         {OBJECT_SELECT_LINKED_PARTICLE, "PARTICLE", 0, "Particle System", ""},
273         {OBJECT_SELECT_LINKED_LIBRARY, "LIBRARY", 0, "Library", ""},
274         {OBJECT_SELECT_LINKED_LIBRARY_OBDATA, "LIBRARY_OBDATA", 0, "Library (Object Data)", ""},
275         {0, NULL, 0, NULL, NULL}
276 };
277
278 static bool object_select_all_by_obdata(bContext *C, void *obdata)
279 {
280         bool changed = false;
281
282         CTX_DATA_BEGIN (C, Base *, base, visible_bases)
283         {
284                 if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
285                         if (base->object->data == obdata) {
286                                 ED_object_base_select(base, BA_SELECT);
287                                 changed = true;
288                         }
289                 }
290         }
291         CTX_DATA_END;
292
293         return changed;
294 }
295
296 static bool object_select_all_by_material_texture(bContext *C, int use_texture, Material *mat, Tex *tex)
297 {
298         bool changed = false;
299
300         CTX_DATA_BEGIN (C, Base *, base, visible_bases)
301         {
302                 if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
303                         Object *ob = base->object;
304                         Material *mat1;
305                         int a, b;
306
307                         for (a = 1; a <= ob->totcol; a++) {
308                                 mat1 = give_current_material(ob, a);
309
310                                 if (!use_texture) {
311                                         if (mat1 == mat) {
312                                                 ED_object_base_select(base, BA_SELECT);
313                                                 changed = true;
314                                         }
315                                 }
316                                 else if (mat1 && use_texture) {
317                                         for (b = 0; b < MAX_MTEX; b++) {
318                                                 if (mat1->mtex[b]) {
319                                                         if (tex == mat1->mtex[b]->tex) {
320                                                                 ED_object_base_select(base, BA_SELECT);
321                                                                 changed = true;
322                                                                 break;
323                                                         }
324                                                 }
325                                         }
326                                 }
327                         }
328                 }
329         }
330         CTX_DATA_END;
331
332         return changed;
333 }
334
335 static bool object_select_all_by_dup_group(bContext *C, Object *ob)
336 {
337         bool changed = false;
338         Group *dup_group = (ob->transflag & OB_DUPLIGROUP) ? ob->dup_group : NULL;
339
340         CTX_DATA_BEGIN (C, Base *, base, visible_bases)
341         {
342                 if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
343                         Group *dup_group_other = (base->object->transflag & OB_DUPLIGROUP) ? base->object->dup_group : NULL;
344                         if (dup_group == dup_group_other) {
345                                 ED_object_base_select(base, BA_SELECT);
346                                 changed = true;
347                         }
348                 }
349         }
350         CTX_DATA_END;
351
352         return changed;
353 }
354
355 static bool object_select_all_by_particle(bContext *C, Object *ob)
356 {
357         ParticleSystem *psys_act = psys_get_current(ob);
358         bool changed = false;
359
360         CTX_DATA_BEGIN (C, Base *, base, visible_bases)
361         {
362                 if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
363                         /* loop through other particles*/
364                         ParticleSystem *psys;
365                         
366                         for (psys = base->object->particlesystem.first; psys; psys = psys->next) {
367                                 if (psys->part == psys_act->part) {
368                                         ED_object_base_select(base, BA_SELECT);
369                                         changed = true;
370                                         break;
371                                 }
372
373                                 if (base->flag & BASE_SELECTED) {
374                                         break;
375                                 }
376                         }
377                 }
378         }
379         CTX_DATA_END;
380
381         return changed;
382 }
383
384 static bool object_select_all_by_library(bContext *C, Library *lib)
385 {
386         bool changed = false;
387
388         CTX_DATA_BEGIN (C, Base *, base, visible_bases)
389         {
390                 if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
391                         if (lib == base->object->id.lib) {
392                                 ED_object_base_select(base, BA_SELECT);
393                                 changed = true;
394                         }
395                 }
396         }
397         CTX_DATA_END;
398
399         return changed;
400 }
401
402 static bool object_select_all_by_library_obdata(bContext *C, Library *lib)
403 {
404         bool changed = false;
405
406         CTX_DATA_BEGIN (C, Base *, base, visible_bases)
407         {
408                 if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
409                         if (base->object->data && lib == ((ID *)base->object->data)->lib) {
410                                 ED_object_base_select(base, BA_SELECT);
411                                 changed = true;
412                         }
413                 }
414         }
415         CTX_DATA_END;
416
417         return changed;
418 }
419
420 void ED_object_select_linked_by_id(bContext *C, ID *id)
421 {
422         int idtype = GS(id->name);
423         bool changed = false;
424
425         if (OB_DATA_SUPPORT_ID(idtype)) {
426                 changed = object_select_all_by_obdata(C, id);
427         }
428         else if (idtype == ID_MA) {
429                 changed = object_select_all_by_material_texture(C, false, (Material *)id, NULL);
430         }
431         else if (idtype == ID_LI) {
432                 changed = object_select_all_by_library(C, (Library *) id);
433         }
434
435         if (changed) {
436                 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
437         }
438 }
439
440 static int object_select_linked_exec(bContext *C, wmOperator *op)
441 {
442         Scene *scene = CTX_data_scene(C);
443         ViewLayer *view_layer = CTX_data_view_layer(C);
444         Object *ob;
445         int nr = RNA_enum_get(op->ptr, "type");
446         bool changed = false, extend;
447
448         extend = RNA_boolean_get(op->ptr, "extend");
449         
450         if (extend == 0) {
451                 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
452                 {
453                         ED_object_base_select(base, BA_DESELECT);
454                 }
455                 CTX_DATA_END;
456         }
457         
458         ob = OBACT(view_layer);
459         if (ob == NULL) {
460                 BKE_report(op->reports, RPT_ERROR, "No active object");
461                 return OPERATOR_CANCELLED;
462         }
463         
464         if (nr == OBJECT_SELECT_LINKED_IPO) {
465                 // XXX old animation system
466                 //if (ob->ipo == 0) return OPERATOR_CANCELLED;
467                 //object_select_all_by_ipo(C, ob->ipo)
468                 return OPERATOR_CANCELLED;
469         }
470         else if (nr == OBJECT_SELECT_LINKED_OBDATA) {
471                 if (ob->data == NULL)
472                         return OPERATOR_CANCELLED;
473
474                 changed = object_select_all_by_obdata(C, ob->data);
475         }
476         else if (nr == OBJECT_SELECT_LINKED_MATERIAL || nr == OBJECT_SELECT_LINKED_TEXTURE) {
477                 Material *mat = NULL;
478                 Tex *tex = NULL;
479                 bool use_texture = false;
480
481                 mat = give_current_material(ob, ob->actcol);
482                 if (mat == NULL) return OPERATOR_CANCELLED;
483                 if (nr == OBJECT_SELECT_LINKED_TEXTURE) {
484                         use_texture = true;
485
486                         if (mat->mtex[(int)mat->texact]) tex = mat->mtex[(int)mat->texact]->tex;
487                         if (tex == NULL) return OPERATOR_CANCELLED;
488                 }
489
490                 changed = object_select_all_by_material_texture(C, use_texture, mat, tex);
491         }
492         else if (nr == OBJECT_SELECT_LINKED_DUPGROUP) {
493                 if (ob->dup_group == NULL)
494                         return OPERATOR_CANCELLED;
495
496                 changed = object_select_all_by_dup_group(C, ob);
497         }
498         else if (nr == OBJECT_SELECT_LINKED_PARTICLE) {
499                 if (BLI_listbase_is_empty(&ob->particlesystem))
500                         return OPERATOR_CANCELLED;
501
502                 changed = object_select_all_by_particle(C, ob);
503         }
504         else if (nr == OBJECT_SELECT_LINKED_LIBRARY) {
505                 /* do nothing */
506                 changed = object_select_all_by_library(C, ob->id.lib);
507         }
508         else if (nr == OBJECT_SELECT_LINKED_LIBRARY_OBDATA) {
509                 if (ob->data == NULL)
510                         return OPERATOR_CANCELLED;
511
512                 changed = object_select_all_by_library_obdata(C, ((ID *) ob->data)->lib);
513         }
514         else
515                 return OPERATOR_CANCELLED;
516
517         if (changed) {
518                 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
519                 return OPERATOR_FINISHED;
520         }
521         
522         return OPERATOR_CANCELLED;
523 }
524
525 void OBJECT_OT_select_linked(wmOperatorType *ot)
526 {
527         /* identifiers */
528         ot->name = "Select Linked";
529         ot->description = "Select all visible objects that are linked";
530         ot->idname = "OBJECT_OT_select_linked";
531         
532         /* api callbacks */
533         ot->invoke = WM_menu_invoke;
534         ot->exec = object_select_linked_exec;
535         ot->poll = objects_selectable_poll;
536         
537         /* flags */
538         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
539         
540         /* properties */
541         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
542         ot->prop = RNA_def_enum(ot->srna, "type", prop_select_linked_types, 0, "Type", "");
543 }
544
545 /*********************** Selected Grouped ********************/
546
547 enum {
548         OBJECT_GRPSEL_CHILDREN_RECURSIVE =  0,
549         OBJECT_GRPSEL_CHILDREN           =  1,
550         OBJECT_GRPSEL_PARENT             =  2,
551         OBJECT_GRPSEL_SIBLINGS           =  3,
552         OBJECT_GRPSEL_TYPE               =  4,
553         /*OBJECT_GRPSEL_LAYER              =  5,*/
554         OBJECT_GRPSEL_GROUP              =  6,
555         OBJECT_GRPSEL_HOOK               =  7,
556         OBJECT_GRPSEL_PASS               =  8,
557         OBJECT_GRPSEL_COLOR              =  9,
558         OBJECT_GRPSEL_PROPERTIES         = 10,
559         OBJECT_GRPSEL_KEYINGSET          = 11,
560         OBJECT_GRPSEL_LAMP_TYPE          = 12,
561 };
562
563 static const EnumPropertyItem prop_select_grouped_types[] = {
564         {OBJECT_GRPSEL_CHILDREN_RECURSIVE, "CHILDREN_RECURSIVE", 0, "Children", ""},
565         {OBJECT_GRPSEL_CHILDREN, "CHILDREN", 0, "Immediate Children", ""},
566         {OBJECT_GRPSEL_PARENT, "PARENT", 0, "Parent", ""},
567         {OBJECT_GRPSEL_SIBLINGS, "SIBLINGS", 0, "Siblings", "Shared Parent"},
568         {OBJECT_GRPSEL_TYPE, "TYPE", 0, "Type", "Shared object type"},
569         {OBJECT_GRPSEL_GROUP, "GROUP", 0, "Group", "Shared group"},
570         {OBJECT_GRPSEL_HOOK, "HOOK", 0, "Hook", ""},
571         {OBJECT_GRPSEL_PASS, "PASS", 0, "Pass", "Render pass Index"},
572         {OBJECT_GRPSEL_COLOR, "COLOR", 0, "Color", "Object Color"},
573         {OBJECT_GRPSEL_PROPERTIES, "PROPERTIES", 0, "Properties", "Game Properties"},
574         {OBJECT_GRPSEL_KEYINGSET, "KEYINGSET", 0, "Keying Set", "Objects included in active Keying Set"},
575         {OBJECT_GRPSEL_LAMP_TYPE, "LAMP_TYPE", 0, "Lamp Type", "Matching lamp types"},
576         {0, NULL, 0, NULL, NULL}
577 };
578
579 static bool select_grouped_children(bContext *C, Object *ob, const bool recursive)
580 {
581         bool changed = false;
582
583         CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
584         {
585                 if (ob == base->object->parent) {
586                         if ((base->flag & BASE_SELECTED) == 0) {
587                                 ED_object_base_select(base, BA_SELECT);
588                                 changed = true;
589                         }
590
591                         if (recursive) {
592                                 changed |= select_grouped_children(C, base->object, 1);
593                         }
594                 }
595         }
596         CTX_DATA_END;
597         return changed;
598 }
599
600 static bool select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */
601 {
602         ViewLayer *view_layer = CTX_data_view_layer(C);
603         Base *baspar, *basact = CTX_data_active_base(C);
604         bool changed = false;
605
606         if (!basact || !(basact->object->parent)) {
607                 return 0;  /* we know OBACT is valid */
608         }
609
610         baspar = BKE_view_layer_base_find(view_layer, basact->object->parent);
611
612         /* can be NULL if parent in other scene */
613         if (baspar && BASE_SELECTABLE(baspar)) {
614                 ED_object_base_select(baspar, BA_SELECT);
615                 ED_object_base_activate(C, baspar);
616                 changed = true;
617         }
618         return changed;
619 }
620
621
622 #define GROUP_MENU_MAX  24
623 static bool select_grouped_group(bContext *C, Object *ob)  /* Select objects in the same group as the active */
624 {
625         bool changed = false;
626         Group *group, *ob_groups[GROUP_MENU_MAX];
627         int group_count = 0, i;
628         uiPopupMenu *pup;
629         uiLayout *layout;
630
631         for (group = CTX_data_main(C)->group.first; group && group_count < GROUP_MENU_MAX; group = group->id.next) {
632                 if (BKE_group_object_exists(group, ob)) {
633                         ob_groups[group_count] = group;
634                         group_count++;
635                 }
636         }
637
638         if (!group_count)
639                 return 0;
640         else if (group_count == 1) {
641                 group = ob_groups[0];
642                 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
643                 {
644                         if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
645                                 if (BKE_group_object_exists(group, base->object)) {
646                                         ED_object_base_select(base, BA_SELECT);
647                                         changed = true;
648                                 }
649                         }
650                 }
651                 CTX_DATA_END;
652                 return changed;
653         }
654
655         /* build the menu. */
656         pup = UI_popup_menu_begin(C, IFACE_("Select Group"), ICON_NONE);
657         layout = UI_popup_menu_layout(pup);
658
659         for (i = 0; i < group_count; i++) {
660                 group = ob_groups[i];
661                 uiItemStringO(layout, group->id.name + 2, 0, "OBJECT_OT_select_same_group", "group", group->id.name + 2);
662         }
663
664         UI_popup_menu_end(C, pup);
665         return changed;  /* The operator already handle this! */
666 }
667
668 static bool select_grouped_object_hooks(bContext *C, Object *ob)
669 {
670         ViewLayer *view_layer = CTX_data_view_layer(C);
671
672         bool changed = false;
673         Base *base;
674         ModifierData *md;
675         HookModifierData *hmd;
676
677         for (md = ob->modifiers.first; md; md = md->next) {
678                 if (md->type == eModifierType_Hook) {
679                         hmd = (HookModifierData *) md;
680                         if (hmd->object) {
681                                 base = BKE_view_layer_base_find(view_layer, hmd->object);
682                                 if (base && ((base->flag & BASE_SELECTED) == 0) && (BASE_SELECTABLE(base))) {
683                                         ED_object_base_select(base, BA_SELECT);
684                                         changed = true;
685                                 }
686                         }
687                 }
688         }
689         return changed;
690 }
691
692 /* Select objects with the same parent as the active (siblings),
693  * parent can be NULL also */
694 static bool select_grouped_siblings(bContext *C, Object *ob)
695 {
696         bool changed = false;
697
698         CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
699         {
700                 if ((base->object->parent == ob->parent) && ((base->flag & BASE_SELECTED) == 0)) {
701                         ED_object_base_select(base, BA_SELECT);
702                         changed = true;
703                 }
704         }
705         CTX_DATA_END;
706         return changed;
707 }
708 static bool select_grouped_lamptype(bContext *C, Object *ob)
709 {
710         Lamp *la = ob->data;
711
712         bool changed = false;
713
714         CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
715         {
716                 if (base->object->type == OB_LAMP) {
717                         Lamp *la_test = base->object->data;
718                         if ((la->type == la_test->type) && ((base->flag & BASE_SELECTED) == 0)) {
719                                 ED_object_base_select(base, BA_SELECT);
720                                 changed = true;
721                         }
722                 }
723         }
724         CTX_DATA_END;
725         return changed;
726 }
727 static bool select_grouped_type(bContext *C, Object *ob)
728 {
729         bool changed = false;
730
731         CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
732         {
733                 if ((base->object->type == ob->type) && ((base->flag & BASE_SELECTED) == 0)) {
734                         ED_object_base_select(base, BA_SELECT);
735                         changed = true;
736                 }
737         }
738         CTX_DATA_END;
739         return changed;
740 }
741
742 static bool select_grouped_index_object(bContext *C, Object *ob)
743 {
744         bool changed = false;
745
746         CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
747         {
748                 if ((base->object->index == ob->index) && ((base->flag & BASE_SELECTED) == 0)) {
749                         ED_object_base_select(base, BA_SELECT);
750                         changed = true;
751                 }
752         }
753         CTX_DATA_END;
754         return changed;
755 }
756
757 static bool select_grouped_color(bContext *C, Object *ob)
758 {
759         bool changed = false;
760
761         CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
762         {
763                 if (((base->flag & BASE_SELECTED) == 0) && (compare_v3v3(base->object->col, ob->col, 0.005f))) {
764                         ED_object_base_select(base, BA_SELECT);
765                         changed = true;
766                 }
767         }
768         CTX_DATA_END;
769         return changed;
770 }
771
772 static bool objects_share_gameprop(Object *a, Object *b)
773 {
774         bProperty *prop;
775
776         for (prop = a->prop.first; prop; prop = prop->next) {
777                 if (BKE_bproperty_object_get(b, prop->name)) {
778                         return 1;
779                 }
780         }
781         return 0;
782 }
783
784 static bool select_grouped_gameprops(bContext *C, Object *ob)
785 {
786         bool changed = false;
787
788         CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
789         {
790                 if (((base->flag & BASE_SELECTED) == 0) && (objects_share_gameprop(base->object, ob))) {
791                         ED_object_base_select(base, BA_SELECT);
792                         changed = true;
793                 }
794         }
795         CTX_DATA_END;
796         return changed;
797 }
798
799 static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList *reports)
800 {
801         KeyingSet *ks = ANIM_scene_get_active_keyingset(CTX_data_scene(C));
802         bool changed = false;
803         
804         /* firstly, validate KeyingSet */
805         if (ks == NULL) {
806                 BKE_report(reports, RPT_ERROR, "No active Keying Set to use");
807                 return false;
808         }
809         else if (ANIM_validate_keyingset(C, NULL, ks) != 0) {
810                 if (ks->paths.first == NULL) {
811                         if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
812                                 BKE_report(reports, RPT_ERROR, 
813                                            "Use another Keying Set, as the active one depends on the currently "
814                                            "selected objects or cannot find any targets due to unsuitable context");
815                         }
816                         else {
817                                 BKE_report(reports, RPT_ERROR, "Keying Set does not contain any paths");
818                         }
819                 }
820                 return false;
821         }
822         
823         /* select each object that Keying Set refers to */
824         /* TODO: perhaps to be more in line with the rest of these, we should only take objects
825          * if the passed in object is included in this too */
826         CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
827         {
828                 /* only check for this object if it isn't selected already, to limit time wasted */
829                 if ((base->flag & BASE_SELECTED) == 0) {
830                         KS_Path *ksp;
831                         
832                         /* this is the slow way... we could end up with > 500 items here, 
833                          * with none matching, but end up doing this on 1000 objects...
834                          */
835                         for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
836                                 /* if id matches, select then stop looping (match found) */
837                                 if (ksp->id == (ID *)base->object) {
838                                         ED_object_base_select(base, BA_SELECT);
839                                         changed = true;
840                                         break;
841                                 }
842                         }
843                 }
844         }
845         CTX_DATA_END;
846                 
847         return changed;
848 }
849
850 static int object_select_grouped_exec(bContext *C, wmOperator *op)
851 {
852         Scene *scene = CTX_data_scene(C);
853         ViewLayer *view_layer = CTX_data_view_layer(C);
854         Object *ob;
855         const int type = RNA_enum_get(op->ptr, "type");
856         bool changed = false, extend;
857
858         extend = RNA_boolean_get(op->ptr, "extend");
859
860         if (extend == 0) {
861                 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
862                 {
863                         ED_object_base_select(base, BA_DESELECT);
864                         changed = true;
865                 }
866                 CTX_DATA_END;
867         }
868
869         ob = OBACT(view_layer);
870         if (ob == NULL) {
871                 BKE_report(op->reports, RPT_ERROR, "No active object");
872                 return OPERATOR_CANCELLED;
873         }
874
875         switch (type) {
876                 case OBJECT_GRPSEL_CHILDREN_RECURSIVE:
877                         changed |= select_grouped_children(C, ob, true);
878                         break;
879                 case OBJECT_GRPSEL_CHILDREN:
880                         changed |= select_grouped_children(C, ob, false);
881                         break;
882                 case OBJECT_GRPSEL_PARENT:
883                         changed |= select_grouped_parent(C);
884                         break;
885                 case OBJECT_GRPSEL_SIBLINGS:
886                         changed |= select_grouped_siblings(C, ob);
887                         break;
888                 case OBJECT_GRPSEL_TYPE:
889                         changed |= select_grouped_type(C, ob);
890                         break;
891                 case OBJECT_GRPSEL_GROUP:
892                         changed |= select_grouped_group(C, ob);
893                         break;
894                 case OBJECT_GRPSEL_HOOK:
895                         changed |= select_grouped_object_hooks(C, ob);
896                         break;
897                 case OBJECT_GRPSEL_PASS:
898                         changed |= select_grouped_index_object(C, ob);
899                         break;
900                 case OBJECT_GRPSEL_COLOR:
901                         changed |= select_grouped_color(C, ob);
902                         break;
903                 case OBJECT_GRPSEL_PROPERTIES:
904                         changed |= select_grouped_gameprops(C, ob);
905                         break;
906                 case OBJECT_GRPSEL_KEYINGSET:
907                         changed |= select_grouped_keyingset(C, ob, op->reports);
908                         break;
909                 case OBJECT_GRPSEL_LAMP_TYPE:
910                         if (ob->type != OB_LAMP) {
911                                 BKE_report(op->reports, RPT_ERROR, "Active object must be a lamp");
912                                 break;
913                         }
914                         changed |= select_grouped_lamptype(C, ob);
915                         break;
916                 default:
917                         break;
918         }
919
920         if (changed) {
921                 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
922                 return OPERATOR_FINISHED;
923         }
924
925         return OPERATOR_CANCELLED;
926 }
927
928 void OBJECT_OT_select_grouped(wmOperatorType *ot)
929 {
930         /* identifiers */
931         ot->name = "Select Grouped";
932         ot->description = "Select all visible objects grouped by various properties";
933         ot->idname = "OBJECT_OT_select_grouped";
934         
935         /* api callbacks */
936         ot->invoke = WM_menu_invoke;
937         ot->exec = object_select_grouped_exec;
938         ot->poll = objects_selectable_poll;
939         
940         /* flags */
941         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
942         
943         /* properties */
944         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
945         ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
946 }
947
948 /**************************** (De)select All ****************************/
949
950 static int object_select_all_exec(bContext *C, wmOperator *op)
951 {
952         int action = RNA_enum_get(op->ptr, "action");
953         
954         /* passthrough if no objects are visible */
955         if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH;
956
957         if (action == SEL_TOGGLE) {
958                 action = SEL_SELECT;
959                 CTX_DATA_BEGIN (C, Base *, base, visible_bases)
960                 {
961                         if ((base->flag & BASE_SELECTED) != 0) {
962                                 action = SEL_DESELECT;
963                                 break;
964                         }
965                 }
966                 CTX_DATA_END;
967         }
968
969         CTX_DATA_BEGIN (C, Base *, base, visible_bases)
970         {
971                 switch (action) {
972                         case SEL_SELECT:
973                                 ED_object_base_select(base, BA_SELECT);
974                                 break;
975                         case SEL_DESELECT:
976                                 ED_object_base_select(base, BA_DESELECT);
977                                 break;
978                         case SEL_INVERT:
979                                 if ((base->flag & BASE_SELECTED) != 0) {
980                                         ED_object_base_select(base, BA_DESELECT);
981                                 }
982                                 else {
983                                         ED_object_base_select(base, BA_SELECT);
984                                 }
985                                 break;
986                 }
987         }
988         CTX_DATA_END;
989         
990         WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
991         
992         return OPERATOR_FINISHED;
993 }
994
995 void OBJECT_OT_select_all(wmOperatorType *ot)
996 {
997         
998         /* identifiers */
999         ot->name = "(De)select All";
1000         ot->description = "Change selection of all visible objects in scene";
1001         ot->idname = "OBJECT_OT_select_all";
1002         
1003         /* api callbacks */
1004         ot->exec = object_select_all_exec;
1005         ot->poll = objects_selectable_poll;
1006         
1007         /* flags */
1008         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1009
1010         WM_operator_properties_select_all(ot);
1011 }
1012
1013 /**************************** Select In The Same Group ****************************/
1014
1015 static int object_select_same_group_exec(bContext *C, wmOperator *op)
1016 {
1017         Group *group;
1018         char group_name[MAX_ID_NAME];
1019
1020         /* passthrough if no objects are visible */
1021         if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH;
1022
1023         RNA_string_get(op->ptr, "group", group_name);
1024
1025         group = (Group *)BKE_libblock_find_name(ID_GR, group_name);
1026
1027         if (!group) {
1028                 return OPERATOR_PASS_THROUGH;
1029         }
1030
1031         CTX_DATA_BEGIN (C, Base *, base, visible_bases)
1032         {
1033                 if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
1034                         if (BKE_group_object_exists(group, base->object)) {
1035                                 ED_object_base_select(base, BA_SELECT);
1036                         }
1037                 }
1038         }
1039         CTX_DATA_END;
1040
1041         WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
1042         
1043         return OPERATOR_FINISHED;
1044 }
1045
1046 void OBJECT_OT_select_same_group(wmOperatorType *ot)
1047 {
1048         
1049         /* identifiers */
1050         ot->name = "Select Same Group";
1051         ot->description = "Select object in the same group";
1052         ot->idname = "OBJECT_OT_select_same_group";
1053         
1054         /* api callbacks */
1055         ot->exec = object_select_same_group_exec;
1056         ot->poll = objects_selectable_poll;
1057         
1058         /* flags */
1059         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1060
1061         RNA_def_string(ot->srna, "group", NULL, MAX_ID_NAME, "Group", "Name of the group to select");
1062 }
1063
1064 /**************************** Select Mirror ****************************/
1065 static int object_select_mirror_exec(bContext *C, wmOperator *op)
1066 {
1067         Scene *scene = CTX_data_scene(C);
1068         ViewLayer *view_layer = CTX_data_view_layer(C);
1069         bool extend;
1070         
1071         extend = RNA_boolean_get(op->ptr, "extend");
1072         
1073         CTX_DATA_BEGIN (C, Base *, primbase, selected_bases)
1074         {
1075                 char name_flip[MAXBONENAME];
1076
1077                 BLI_string_flip_side_name(name_flip, primbase->object->id.name + 2, true, sizeof(name_flip));
1078                 
1079                 if (!STREQ(name_flip, primbase->object->id.name + 2)) {
1080                         Object *ob = (Object *)BKE_libblock_find_name(ID_OB, name_flip);
1081                         if (ob) {
1082                                 Base *secbase = BKE_view_layer_base_find(view_layer, ob);
1083
1084                                 if (secbase) {
1085                                         ED_object_base_select(secbase, BA_SELECT);
1086                                 }
1087                         }
1088                 }
1089                 
1090                 if (extend == false) ED_object_base_select(primbase, BA_DESELECT);
1091                 
1092         }
1093         CTX_DATA_END;
1094         
1095         /* undo? */
1096         WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
1097         
1098         return OPERATOR_FINISHED;
1099 }
1100
1101 void OBJECT_OT_select_mirror(wmOperatorType *ot)
1102 {
1103         
1104         /* identifiers */
1105         ot->name = "Select Mirror";
1106         ot->description = "Select the Mirror objects of the selected object eg. L.sword -> R.sword";
1107         ot->idname = "OBJECT_OT_select_mirror";
1108         
1109         /* api callbacks */
1110         ot->exec = object_select_mirror_exec;
1111         ot->poll = objects_selectable_poll;
1112         
1113         /* flags */
1114         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1115         
1116         RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first");
1117 }
1118
1119
1120 /** \name Select More/Less
1121  * \{ */
1122
1123 static bool object_select_more_less(bContext *C, const bool select)
1124 {
1125         ViewLayer *view_layer = CTX_data_view_layer(C);
1126
1127         for (Base *base = view_layer->object_bases.first; base; base = base->next) {
1128                 Object *ob = base->object;
1129                 ob->flag &= ~OB_DONE;
1130                 ob->id.tag &= ~LIB_TAG_DOIT;
1131                 /* parent may be in another scene */
1132                 if (ob->parent) {
1133                         ob->parent->flag &= ~OB_DONE;
1134                         ob->parent->id.tag &= ~LIB_TAG_DOIT;
1135                 }
1136         }
1137
1138         ListBase ctx_base_list;
1139         CollectionPointerLink *ctx_base;
1140         CTX_data_selectable_bases(C, &ctx_base_list);
1141
1142         CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
1143         {
1144                 ob->flag |= OB_DONE;
1145         }
1146         CTX_DATA_END;
1147
1148
1149
1150         for (ctx_base = ctx_base_list.first; ctx_base; ctx_base = ctx_base->next) {
1151                 Object *ob = ((Base *)ctx_base->ptr.data)->object;
1152                 if (ob->parent) {
1153                         if ((ob->flag & OB_DONE) != (ob->parent->flag & OB_DONE)) {
1154                                 ob->id.tag         |= LIB_TAG_DOIT;
1155                                 ob->parent->id.tag |= LIB_TAG_DOIT;
1156                         }
1157                 }
1158         }
1159
1160         bool changed = false;
1161         const short select_mode = select ? BA_SELECT : BA_DESELECT;
1162         const short select_flag = select ? BASE_SELECTED : 0;
1163
1164         for (ctx_base = ctx_base_list.first; ctx_base; ctx_base = ctx_base->next) {
1165                 Base *base = ctx_base->ptr.data;
1166                 Object *ob = base->object;
1167                 if ((ob->id.tag & LIB_TAG_DOIT) && ((base->flag & BASE_SELECTED) != select_flag)) {
1168                         ED_object_base_select(base, select_mode);
1169                         changed = true;
1170                 }
1171         }
1172
1173         BLI_freelistN(&ctx_base_list);
1174
1175         return changed;
1176 }
1177
1178 static int object_select_more_exec(bContext *C, wmOperator *UNUSED(op))
1179 {
1180         bool changed = object_select_more_less(C, true);
1181
1182         if (changed) {
1183                 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
1184                 return OPERATOR_FINISHED;
1185         }
1186         else {
1187                 return OPERATOR_CANCELLED;
1188         }
1189 }
1190
1191 void OBJECT_OT_select_more(wmOperatorType *ot)
1192 {
1193         /* identifiers */
1194         ot->name = "Select More";
1195         ot->idname = "OBJECT_OT_select_more";
1196         ot->description = "Select connected parent/child objects";
1197
1198         /* api callbacks */
1199         ot->exec = object_select_more_exec;
1200         ot->poll = ED_operator_objectmode;
1201
1202         /* flags */
1203         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1204 }
1205
1206 static int object_select_less_exec(bContext *C, wmOperator *UNUSED(op))
1207 {
1208         bool changed = object_select_more_less(C, false);
1209
1210         if (changed) {
1211                 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
1212                 return OPERATOR_FINISHED;
1213         }
1214         else {
1215                 return OPERATOR_CANCELLED;
1216         }
1217 }
1218
1219 void OBJECT_OT_select_less(wmOperatorType *ot)
1220 {
1221         /* identifiers */
1222         ot->name = "Select Less";
1223         ot->idname = "OBJECT_OT_select_less";
1224         ot->description = "Deselect objects at the boundaries of parent/child relationships";
1225
1226         /* api callbacks */
1227         ot->exec = object_select_less_exec;
1228         ot->poll = ED_operator_objectmode;
1229
1230         /* flags */
1231         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1232 }
1233
1234 /** \} */
1235
1236
1237 /**************************** Select Random ****************************/
1238
1239 static int object_select_random_exec(bContext *C, wmOperator *op)
1240 {       
1241         const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
1242         const int seed = WM_operator_properties_select_random_seed_increment_get(op);
1243         const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
1244
1245         RNG *rng = BLI_rng_new_srandom(seed);
1246
1247         CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
1248         {
1249                 if (BLI_rng_get_float(rng) < randfac) {
1250                         ED_object_base_select(base, select);
1251                 }
1252         }
1253         CTX_DATA_END;
1254
1255         BLI_rng_free(rng);
1256
1257         WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
1258         
1259         return OPERATOR_FINISHED;
1260 }
1261
1262 void OBJECT_OT_select_random(wmOperatorType *ot)
1263 {
1264         /* identifiers */
1265         ot->name = "Select Random";
1266         ot->description = "Set select on random visible objects";
1267         ot->idname = "OBJECT_OT_select_random";
1268         
1269         /* api callbacks */
1270         /*ot->invoke = object_select_random_invoke XXX - need a number popup ;*/
1271         ot->exec = object_select_random_exec;
1272         ot->poll = objects_selectable_poll;
1273         
1274         /* flags */
1275         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1276         
1277         /* properties */
1278         WM_operator_properties_select_random(ot);
1279 }