Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / object / object_group.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) Blender Foundation
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/object/object_group.c
29  *  \ingroup edobj
30  */
31
32
33 #include <string.h>
34
35 #include "BLI_blenlib.h"
36 #include "BLI_utildefines.h"
37
38 #include "DNA_group_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_scene_types.h"
41
42 #include "BKE_context.h"
43 #include "BKE_depsgraph.h"
44 #include "BKE_group.h"
45 #include "BKE_library.h"
46 #include "BKE_library_remap.h"
47 #include "BKE_main.h"
48 #include "BKE_report.h"
49 #include "BKE_object.h"
50
51 #include "ED_screen.h"
52 #include "ED_object.h"
53
54 #include "WM_api.h"
55 #include "WM_types.h"
56
57 #include "RNA_access.h"
58 #include "RNA_define.h"
59 #include "RNA_enum_types.h"
60
61 #include "object_intern.h"
62
63 /********************* 3d view operators ***********************/
64
65 /* can be called with C == NULL */
66 static EnumPropertyItem *group_object_active_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
67 {
68         Object *ob;
69         EnumPropertyItem *item = NULL, item_tmp = {0};
70         int totitem = 0;
71
72         if (C == NULL) {
73                 return DummyRNA_NULL_items;
74         }
75
76         ob = ED_object_context(C);
77
78         /* check that the object exists */
79         if (ob) {
80                 Group *group;
81                 int i = 0, count = 0;
82
83                 /* if 2 or more groups, add option to add to all groups */
84                 group = NULL;
85                 while ((group = BKE_group_object_find(group, ob)))
86                         count++;
87
88                 if (count >= 2) {
89                         item_tmp.identifier = item_tmp.name = "All Groups";
90                         item_tmp.value = INT_MAX; /* this will give NULL on lookup */
91                         RNA_enum_item_add(&item, &totitem, &item_tmp);
92                         RNA_enum_item_add_separator(&item, &totitem);
93                 }
94
95                 /* add groups */
96                 group = NULL;
97                 while ((group = BKE_group_object_find(group, ob))) {
98                         item_tmp.identifier = item_tmp.name = group->id.name + 2;
99                         /* item_tmp.icon = ICON_ARMATURE_DATA; */
100                         item_tmp.value = i;
101                         RNA_enum_item_add(&item, &totitem, &item_tmp);
102                         i++;
103                 }
104         }
105
106         RNA_enum_item_end(&item, &totitem);
107         *r_free = true;
108
109         return item;
110 }
111
112 /* get the group back from the enum index, quite awkward and UI specific */
113 static Group *group_object_active_find_index(Object *ob, const int group_object_index)
114 {
115         Group *group = NULL;
116         int i = 0;
117         while ((group = BKE_group_object_find(group, ob))) {
118                 if (i == group_object_index) {
119                         break;
120                 }
121                 i++;
122         }
123
124         return group;
125 }
126
127 static int objects_add_active_exec(bContext *C, wmOperator *op)
128 {
129         Object *ob = ED_object_context(C);
130         Main *bmain = CTX_data_main(C);
131         int single_group_index = RNA_enum_get(op->ptr, "group");
132         Group *single_group = group_object_active_find_index(ob, single_group_index);
133         Group *group;
134         bool is_cycle = false;
135         bool updated = false;
136
137         if (ob == NULL)
138                 return OPERATOR_CANCELLED;
139
140         /* now add all selected objects to the group(s) */
141         for (group = bmain->group.first; group; group = group->id.next) {
142                 if (single_group && group != single_group)
143                         continue;
144                 if (!BKE_group_object_exists(group, ob))
145                         continue;
146
147                 CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
148                 {
149                         if (BKE_group_object_exists(group, base->object))
150                                 continue;
151
152                         if (!BKE_group_object_cyclic_check(bmain, base->object, group)) {
153                                 BKE_group_object_add(group, base->object);
154                                 updated = true;
155                         }
156                         else {
157                                 is_cycle = true;
158                         }
159                 }
160                 CTX_DATA_END;
161         }
162
163         if (is_cycle)
164                 BKE_report(op->reports, RPT_WARNING, "Skipped some groups because of cycle detected");
165
166         if (!updated)
167                 return OPERATOR_CANCELLED;
168
169         DAG_relations_tag_update(bmain);
170         WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
171
172         return OPERATOR_FINISHED;
173 }
174
175 void GROUP_OT_objects_add_active(wmOperatorType *ot)
176 {
177         PropertyRNA *prop;
178
179         /* identifiers */
180         ot->name = "Add Selected To Active Group";
181         ot->description = "Add the object to an object group that contains the active object";
182         ot->idname = "GROUP_OT_objects_add_active";
183         
184         /* api callbacks */
185         ot->exec = objects_add_active_exec;
186         ot->invoke = WM_menu_invoke;
187         ot->poll = ED_operator_objectmode;
188
189         /* flags */
190         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
191
192         /* properties */
193         prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "The group to add other selected objects to");
194         RNA_def_enum_funcs(prop, group_object_active_itemf);
195         RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
196         ot->prop = prop;
197 }
198
199 static int objects_remove_active_exec(bContext *C, wmOperator *op)
200 {
201         Main *bmain = CTX_data_main(C);
202         SceneLayer *sl = CTX_data_scene_layer(C);
203         Object *ob = OBACT_NEW;
204         int single_group_index = RNA_enum_get(op->ptr, "group");
205         Group *single_group = group_object_active_find_index(ob, single_group_index);
206         Group *group;
207         bool ok = false;
208         
209         if (ob == NULL)
210                 return OPERATOR_CANCELLED;
211         
212         /* linking to same group requires its own loop so we can avoid
213          * looking up the active objects groups each time */
214
215         for (group = bmain->group.first; group; group = group->id.next) {
216                 if (single_group && group != single_group)
217                         continue;
218
219                 if (BKE_group_object_exists(group, ob)) {
220                         /* Remove groups from selected objects */
221                         CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
222                         {
223                                 BKE_group_object_unlink(group, base->object);
224                                 ok = 1;
225                         }
226                         CTX_DATA_END;
227                 }
228         }
229         
230         if (!ok)
231                 BKE_report(op->reports, RPT_ERROR, "Active object contains no groups");
232         
233         DAG_relations_tag_update(bmain);
234         WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
235         
236         return OPERATOR_FINISHED;
237 }
238
239 void GROUP_OT_objects_remove_active(wmOperatorType *ot)
240 {
241         PropertyRNA *prop;
242
243         /* identifiers */
244         ot->name = "Remove Selected From Active Group";
245         ot->description = "Remove the object from an object group that contains the active object";
246         ot->idname = "GROUP_OT_objects_remove_active";
247         
248         /* api callbacks */
249         ot->exec = objects_remove_active_exec;
250         ot->invoke = WM_menu_invoke;
251         ot->poll = ED_operator_objectmode;
252         
253         /* flags */
254         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
255
256         /* properties */
257         prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "The group to remove other selected objects from");
258         RNA_def_enum_funcs(prop, group_object_active_itemf);
259         RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
260         ot->prop = prop;
261 }
262
263 static int group_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
264 {
265         Main *bmain = CTX_data_main(C);
266
267         CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
268         {
269                 BKE_object_groups_clear(base->object);
270         }
271         CTX_DATA_END;
272
273         DAG_relations_tag_update(bmain);
274         WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
275         
276         return OPERATOR_FINISHED;
277 }
278
279 void GROUP_OT_objects_remove_all(wmOperatorType *ot)
280 {
281         /* identifiers */
282         ot->name = "Remove From All Groups";
283         ot->description = "Remove selected objects from all groups";
284         ot->idname = "GROUP_OT_objects_remove_all";
285         
286         /* api callbacks */
287         ot->exec = group_objects_remove_all_exec;
288         ot->poll = ED_operator_objectmode;
289         
290         /* flags */
291         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
292 }
293
294 static int group_objects_remove_exec(bContext *C, wmOperator *op)
295 {
296         Object *ob = ED_object_context(C);
297         Main *bmain = CTX_data_main(C);
298         int single_group_index = RNA_enum_get(op->ptr, "group");
299         Group *single_group = group_object_active_find_index(ob, single_group_index);
300         Group *group;
301         bool updated = false;
302
303         if (ob == NULL)
304                 return OPERATOR_CANCELLED;
305
306         for (group = bmain->group.first; group; group = group->id.next) {
307                 if (single_group && group != single_group)
308                         continue;
309                 if (!BKE_group_object_exists(group, ob))
310                         continue;
311
312                 /* now remove all selected objects from the group */
313                 CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
314                 {
315                         BKE_group_object_unlink(group, base->object);
316                         updated = true;
317                 }
318                 CTX_DATA_END;
319         }
320
321         if (!updated)
322                 return OPERATOR_CANCELLED;
323
324         DAG_relations_tag_update(bmain);
325         WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
326
327         return OPERATOR_FINISHED;
328 }
329
330 void GROUP_OT_objects_remove(wmOperatorType *ot)
331 {
332         PropertyRNA *prop;
333
334         /* identifiers */
335         ot->name = "Remove From Group";
336         ot->description = "Remove selected objects from a group";
337         ot->idname = "GROUP_OT_objects_remove";
338
339         /* api callbacks */
340         ot->exec = group_objects_remove_exec;
341         ot->invoke = WM_menu_invoke;
342         ot->poll = ED_operator_objectmode;
343
344         /* flags */
345         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
346
347         /* properties */
348         prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "The group to remove this object from");
349         RNA_def_enum_funcs(prop, group_object_active_itemf);
350         RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
351         ot->prop = prop;
352 }
353
354 static int group_create_exec(bContext *C, wmOperator *op)
355 {
356         Main *bmain = CTX_data_main(C);
357         Group *group = NULL;
358         char name[MAX_ID_NAME - 2]; /* id name */
359         
360         RNA_string_get(op->ptr, "name", name);
361         
362         group = BKE_group_add(bmain, name);
363                 
364         CTX_DATA_BEGIN (C, Base *, base, selected_bases)
365         {
366                 BKE_group_object_add(group, base->object);
367         }
368         CTX_DATA_END;
369
370         DAG_relations_tag_update(bmain);
371         WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
372         
373         return OPERATOR_FINISHED;
374 }
375
376 void GROUP_OT_create(wmOperatorType *ot)
377 {
378         /* identifiers */
379         ot->name = "Create New Group";
380         ot->description = "Create an object group from selected objects";
381         ot->idname = "GROUP_OT_create";
382         
383         /* api callbacks */
384         ot->exec = group_create_exec;
385         ot->poll = ED_operator_objectmode;
386         
387         /* flags */
388         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
389         
390         RNA_def_string(ot->srna, "name", "Group", MAX_ID_NAME - 2, "Name", "Name of the new group");
391 }
392
393 /****************** properties window operators *********************/
394
395 static int group_add_exec(bContext *C, wmOperator *UNUSED(op))
396 {
397         Object *ob = ED_object_context(C);
398         Main *bmain = CTX_data_main(C);
399         Group *group;
400
401         if (ob == NULL)
402                 return OPERATOR_CANCELLED;
403
404         group = BKE_group_add(bmain, "Group");
405         BKE_group_object_add(group, ob);
406
407         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
408
409         return OPERATOR_FINISHED;
410 }
411
412 void OBJECT_OT_group_add(wmOperatorType *ot)
413 {
414         /* identifiers */
415         ot->name = "Add to Group";
416         ot->idname = "OBJECT_OT_group_add";
417         ot->description = "Add an object to a new group";
418         
419         /* api callbacks */
420         ot->exec = group_add_exec;
421         ot->poll = ED_operator_objectmode;
422
423         /* flags */
424         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
425 }
426
427 static int group_link_exec(bContext *C, wmOperator *op)
428 {
429         Main *bmain = CTX_data_main(C);
430         Object *ob = ED_object_context(C);
431         Group *group = BLI_findlink(&bmain->group, RNA_enum_get(op->ptr, "group"));
432
433         if (ELEM(NULL, ob, group))
434                 return OPERATOR_CANCELLED;
435
436         /* Early return check, if the object is already in group
437          * we could skip all the dependency check and just consider
438          * operator is finished.
439          */
440         if (BKE_group_object_exists(group, ob)) {
441                 return OPERATOR_FINISHED;
442         }
443
444         /* Adding object to group which is used as dupligroup for self is bad idea.
445          *
446          * It is also  bad idea to add object to group which is in group which
447          * contains our current object.
448          */
449         if (BKE_group_object_cyclic_check(bmain, ob, group)) {
450                 BKE_report(op->reports, RPT_ERROR, "Could not add the group because of dependency cycle detected");
451                 return OPERATOR_CANCELLED;
452         }
453
454         BKE_group_object_add(group, ob);
455
456         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
457
458         return OPERATOR_FINISHED;
459 }
460
461 void OBJECT_OT_group_link(wmOperatorType *ot)
462 {
463         PropertyRNA *prop;
464
465         /* identifiers */
466         ot->name = "Link to Group";
467         ot->idname = "OBJECT_OT_group_link";
468         ot->description = "Add an object to an existing group";
469         
470         /* api callbacks */
471         ot->exec = group_link_exec;
472         ot->invoke = WM_enum_search_invoke;
473         ot->poll = ED_operator_objectmode;
474
475         /* flags */
476         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
477
478         /* properties */
479         prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "");
480         RNA_def_enum_funcs(prop, RNA_group_local_itemf);
481         RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
482         ot->prop = prop;
483 }
484
485 static int group_remove_exec(bContext *C, wmOperator *UNUSED(op))
486 {
487         Object *ob = ED_object_context(C);
488         Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
489
490         if (!ob || !group)
491                 return OPERATOR_CANCELLED;
492
493         BKE_group_object_unlink(group, ob);
494
495         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
496         
497         return OPERATOR_FINISHED;
498 }
499
500 void OBJECT_OT_group_remove(wmOperatorType *ot)
501 {
502         /* identifiers */
503         ot->name = "Remove Group";
504         ot->idname = "OBJECT_OT_group_remove";
505         ot->description = "Remove the active object from this group";
506         
507         /* api callbacks */
508         ot->exec = group_remove_exec;
509         ot->poll = ED_operator_objectmode;
510
511         /* flags */
512         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
513 }
514
515
516 static int group_unlink_exec(bContext *C, wmOperator *UNUSED(op))
517 {
518         Main *bmain = CTX_data_main(C);
519         Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
520
521         if (!group)
522                 return OPERATOR_CANCELLED;
523
524         BKE_libblock_unlink(bmain, group, false, false);
525         BKE_libblock_free(bmain, group);
526
527         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
528
529         return OPERATOR_FINISHED;
530 }
531
532 void OBJECT_OT_group_unlink(wmOperatorType *ot)
533 {
534         /* identifiers */
535         ot->name = "Unlink Group";
536         ot->idname = "OBJECT_OT_group_unlink";
537         ot->description = "Unlink the group from all objects";
538
539         /* api callbacks */
540         ot->exec = group_unlink_exec;
541         ot->poll = ED_operator_objectmode;
542
543         /* flags */
544         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
545 }
546
547 static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op))  /* Select objects in the same group as the active */
548 {
549         Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
550
551         if (!group)
552                 return OPERATOR_CANCELLED;
553
554         CTX_DATA_BEGIN (C, Base *, base, visible_bases)
555         {
556                 if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
557                         if (BKE_group_object_exists(group, base->object)) {
558                                 ED_object_base_select(base, BA_SELECT);
559                         }
560                 }
561         }
562         CTX_DATA_END;
563
564         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
565
566         return OPERATOR_FINISHED;
567 }
568
569 void OBJECT_OT_grouped_select(wmOperatorType *ot)
570 {
571         /* identifiers */
572         ot->name = "Select Grouped";
573         ot->idname = "OBJECT_OT_grouped_select";
574         ot->description = "Select all objects in group";
575
576         /* api callbacks */
577         ot->exec = select_grouped_exec;
578         ot->poll = ED_operator_objectmode;
579
580         /* flags */
581         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
582 }