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