Rename any instance of scene layer or render layer in code with view layer
[blender.git] / source / blender / editors / space_outliner / outliner_collections.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  * Contributor(s): Blender Foundation, Dalai Felinto
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/editors/space_outliner/outliner_collections.c
24  *  \ingroup spoutliner
25  */
26
27 #include "BLI_utildefines.h"
28 #include "BLI_listbase.h"
29
30 #include "BKE_context.h"
31 #include "BKE_collection.h"
32 #include "BKE_layer.h"
33 #include "BKE_main.h"
34 #include "BKE_report.h"
35
36 #include "DEG_depsgraph.h"
37 #include "DEG_depsgraph_build.h"
38
39 #include "ED_screen.h"
40
41 #include "WM_api.h"
42 #include "WM_types.h"
43
44 #include "RNA_access.h"
45 #include "RNA_define.h"
46 #include "RNA_enum_types.h"
47
48 #include "UI_resources.h"
49
50 #include "outliner_intern.h" /* own include */
51
52 /* -------------------------------------------------------------------- */
53
54 static LayerCollection *outliner_collection_active(bContext *C)
55 {
56         TODO_LAYER_OPERATORS;
57         /* consider that we may have overrides or objects active
58          * leading to no active collections */
59         return CTX_data_layer_collection(C);
60 }
61
62 SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te)
63 {
64         TreeStoreElem *tselem = TREESTORE(te);
65
66         if (tselem->type == TSE_SCENE_COLLECTION) {
67                 return te->directdata;
68         }
69         else if (tselem->type == TSE_LAYER_COLLECTION) {
70                 LayerCollection *lc = te->directdata;
71                 return lc->scene_collection;
72         }
73
74         return NULL;
75 }
76
77 #if 0
78 static CollectionOverride *outliner_override_active(bContext *UNUSED(C))
79 {
80         TODO_LAYER_OPERATORS;
81         TODO_LAYER_OVERRIDE;
82         return NULL;
83 }
84 #endif
85
86 /* -------------------------------------------------------------------- */
87 /* collection manager operators */
88
89 /**
90  * Recursively get the collection for a given index
91  */
92 static SceneCollection *scene_collection_from_index(ListBase *lb, const int number, int *i)
93 {
94         for (SceneCollection *sc = lb->first; sc; sc = sc->next) {
95                 if (*i == number) {
96                         return sc;
97                 }
98
99                 (*i)++;
100
101                 SceneCollection *sc_nested = scene_collection_from_index(&sc->scene_collections, number, i);
102                 if (sc_nested) {
103                         return sc_nested;
104                 }
105         }
106         return NULL;
107 }
108
109 static int collection_link_exec(bContext *C, wmOperator *op)
110 {
111         Scene *scene = CTX_data_scene(C);
112         ViewLayer *sl = CTX_data_view_layer(C);
113         SceneCollection *sc_master = BKE_collection_master(scene);
114         SceneCollection *sc;
115
116         int scene_collection_index = RNA_enum_get(op->ptr, "scene_collection");
117         if (scene_collection_index == 0) {
118                 sc = sc_master;
119         }
120         else {
121                 int index = 1;
122                 sc = scene_collection_from_index(&sc_master->scene_collections, scene_collection_index, &index);
123                 BLI_assert(sc);
124         }
125
126         BKE_collection_link(sl, sc);
127
128         DEG_relations_tag_update(CTX_data_main(C));
129
130         /* TODO(sergey): Use proper flag for tagging here. */
131         DEG_id_tag_update(&scene->id, 0);
132
133         WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
134         return OPERATOR_FINISHED;
135 }
136
137 static int collection_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
138 {
139         if (BKE_collection_master(CTX_data_scene(C))->scene_collections.first == NULL) {
140                 RNA_enum_set(op->ptr, "scene_collection", 0);
141                 return collection_link_exec(C, op);
142         }
143         else {
144                 return WM_enum_search_invoke(C, op, event);
145         }
146 }
147
148 static void collection_scene_collection_itemf_recursive(
149         EnumPropertyItem *tmp, EnumPropertyItem **item, int *totitem, int *value, SceneCollection *sc)
150 {
151         tmp->value = *value;
152         tmp->icon = ICON_COLLAPSEMENU;
153         tmp->identifier = sc->name;
154         tmp->name = sc->name;
155         RNA_enum_item_add(item, totitem, tmp);
156
157         (*value)++;
158
159         for (SceneCollection *ncs = sc->scene_collections.first; ncs; ncs = ncs->next) {
160                 collection_scene_collection_itemf_recursive(tmp, item, totitem, value, ncs);
161         }
162 }
163
164 static const EnumPropertyItem *collection_scene_collection_itemf(
165         bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
166 {
167         EnumPropertyItem tmp = {0, "", 0, "", ""};
168         EnumPropertyItem *item = NULL;
169         int value = 0, totitem = 0;
170
171         Scene *scene = CTX_data_scene(C);
172         SceneCollection *sc = BKE_collection_master(scene);
173
174         collection_scene_collection_itemf_recursive(&tmp, &item, &totitem, &value, sc);
175         RNA_enum_item_end(&item, &totitem);
176         *r_free = true;
177
178         return item;
179 }
180
181 void OUTLINER_OT_collection_link(wmOperatorType *ot)
182 {
183         PropertyRNA *prop;
184
185         /* identifiers */
186         ot->name = "Add Collection";
187         ot->idname = "OUTLINER_OT_collection_link";
188         ot->description = "Link a new collection to the active layer";
189
190         /* api callbacks */
191         ot->exec = collection_link_exec;
192         ot->invoke = collection_link_invoke;
193
194         /* flags */
195         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
196
197         prop = RNA_def_enum(ot->srna, "scene_collection", DummyRNA_NULL_items, 0, "Scene Collection", "");
198         RNA_def_enum_funcs(prop, collection_scene_collection_itemf);
199         RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
200         ot->prop = prop;
201 }
202
203 /**
204  * Returns true if selected element is a collection directly
205  * linked to the active ViewLayer (not a nested collection)
206  */
207 static int collection_unlink_poll(bContext *C)
208 {
209         LayerCollection *lc = outliner_collection_active(C);
210
211         if (lc == NULL) {
212                 return 0;
213         }
214
215         ViewLayer *sl = CTX_data_view_layer(C);
216         return BLI_findindex(&sl->layer_collections, lc) != -1 ? 1 : 0;
217 }
218
219 static int collection_unlink_exec(bContext *C, wmOperator *op)
220 {
221         LayerCollection *lc = outliner_collection_active(C);
222         SpaceOops *soops = CTX_wm_space_outliner(C);
223
224         if (lc == NULL) {
225                 BKE_report(op->reports, RPT_ERROR, "Active element is not a collection");
226                 return OPERATOR_CANCELLED;
227         }
228
229         ViewLayer *sl = CTX_data_view_layer(C);
230         BKE_collection_unlink(sl, lc);
231
232         if (soops) {
233                 outliner_cleanup_tree(soops);
234         }
235
236         DEG_relations_tag_update(CTX_data_main(C));
237
238         /* TODO(sergey): Use proper flag for tagging here. */
239         DEG_id_tag_update(&CTX_data_scene(C)->id, 0);
240
241         WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
242         return OPERATOR_FINISHED;
243 }
244
245 void OUTLINER_OT_collection_unlink(wmOperatorType *ot)
246 {
247         /* identifiers */
248         ot->name = "Add Collection";
249         ot->idname = "OUTLINER_OT_collection_unlink";
250         ot->description = "Unlink collection from the active layer";
251
252         /* api callbacks */
253         ot->exec = collection_unlink_exec;
254         ot->poll = collection_unlink_poll;
255
256         /* flags */
257         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
258 }
259
260 static int collection_new_exec(bContext *C, wmOperator *UNUSED(op))
261 {
262         Scene *scene = CTX_data_scene(C);
263         ViewLayer *sl = CTX_data_view_layer(C);
264
265         SceneCollection *sc = BKE_collection_add(scene, NULL, NULL);
266         BKE_collection_link(sl, sc);
267
268         DEG_relations_tag_update(CTX_data_main(C));
269         WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
270         return OPERATOR_FINISHED;
271 }
272
273 void OUTLINER_OT_collection_new(wmOperatorType *ot)
274 {
275         /* identifiers */
276         ot->name = "New Collection";
277         ot->idname = "OUTLINER_OT_collection_new";
278         ot->description = "Add a new collection to the scene, and link it to the active layer";
279
280         /* api callbacks */
281         ot->exec = collection_new_exec;
282
283         /* flags */
284         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
285 }
286
287 /**
288  * Returns true is selected element is a collection
289  */
290 static int collection_override_new_poll(bContext *(C))
291 {
292 #ifdef TODO_LAYER_OVERRIDE
293         /* disable for now, since it's not implemented */
294         (void) C;
295         return 0;
296 #else
297         return outliner_collection_active(C) ? 1 : 0;
298 #endif
299 }
300
301 static int collection_override_new_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
302 {
303         TODO_LAYER_OPERATORS;
304         TODO_LAYER_OVERRIDE;
305         BKE_report(op->reports, RPT_ERROR, "OUTLINER_OT_collections_override_new not implemented yet");
306         return OPERATOR_CANCELLED;
307 }
308
309 /* in the middle of renames remove s */
310 void OUTLINER_OT_collection_override_new(wmOperatorType *ot)
311 {
312         /* identifiers */
313         ot->name = "New Override";
314         ot->idname = "OUTLINER_OT_collection_override_new";
315         ot->description = "Add a new override to the active collection";
316
317         /* api callbacks */
318         ot->invoke = collection_override_new_invoke;
319         ot->poll = collection_override_new_poll;
320
321         /* flags */
322         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
323 }
324
325 struct CollectionDeleteData {
326         Scene *scene;
327         SpaceOops *soops;
328 };
329
330 static TreeTraversalAction collection_delete_cb(TreeElement *te, void *customdata)
331 {
332         struct CollectionDeleteData *data = customdata;
333         SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
334
335         if (!scene_collection) {
336                 return TRAVERSE_SKIP_CHILDS;
337         }
338
339         if (scene_collection == BKE_collection_master(data->scene)) {
340                 /* skip - showing warning/error message might be missleading
341                  * when deleting multiple collections, so just do nothing */
342         }
343         else {
344                 BKE_collection_remove(data->scene, scene_collection);
345         }
346
347         return TRAVERSE_CONTINUE;
348 }
349
350 static int collection_delete_exec(bContext *C, wmOperator *UNUSED(op))
351 {
352         Scene *scene = CTX_data_scene(C);
353         SpaceOops *soops = CTX_wm_space_outliner(C);
354         struct CollectionDeleteData data = {.scene = scene, .soops = soops};
355
356         TODO_LAYER_OVERRIDE; /* handle overrides */
357         outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_delete_cb, &data);
358
359         DEG_relations_tag_update(CTX_data_main(C));
360
361         /* TODO(sergey): Use proper flag for tagging here. */
362         DEG_id_tag_update(&scene->id, 0);
363
364         WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
365
366         return OPERATOR_FINISHED;
367 }
368
369 void OUTLINER_OT_collections_delete(wmOperatorType *ot)
370 {
371         /* identifiers */
372         ot->name = "Delete";
373         ot->idname = "OUTLINER_OT_collections_delete";
374         ot->description = "Delete selected overrides or collections";
375
376         /* api callbacks */
377         ot->exec = collection_delete_exec;
378
379         /* flags */
380         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
381 }
382
383 static int collection_select_exec(bContext *C, wmOperator *op)
384 {
385         ViewLayer *sl = CTX_data_view_layer(C);
386         const int collection_index = RNA_int_get(op->ptr, "collection_index");
387         sl->active_collection = collection_index;
388         WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
389         return OPERATOR_FINISHED;
390 }
391
392 void OUTLINER_OT_collection_select(wmOperatorType *ot)
393 {
394         /* identifiers */
395         ot->name = "Select";
396         ot->idname = "OUTLINER_OT_collection_select";
397         ot->description = "Change active collection or override";
398
399         /* api callbacks */
400         ot->exec = collection_select_exec;
401
402         /* flags */
403         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
404
405         RNA_def_int(ot->srna, "collection_index", 0, 0, INT_MAX, "Index",
406                     "Index of collection to select", 0, INT_MAX);
407 }
408
409 #define ACTION_DISABLE 0
410 #define ACTION_ENABLE 1
411 #define ACTION_TOGGLE 2
412
413 static int collection_toggle_exec(bContext *C, wmOperator *op)
414 {
415         Main *bmain = CTX_data_main(C);
416         Scene *scene = CTX_data_scene(C);
417         ViewLayer *view_layer = CTX_data_view_layer(C);
418         int action = RNA_enum_get(op->ptr, "action");
419         LayerCollection *layer_collection = CTX_data_layer_collection(C);
420
421         if (layer_collection->flag & COLLECTION_DISABLED) {
422                 if (ELEM(action, ACTION_TOGGLE, ACTION_ENABLE)) {
423                         BKE_collection_enable(view_layer, layer_collection);
424                 }
425                 else { /* ACTION_DISABLE */
426                         BKE_reportf(op->reports, RPT_ERROR, "Layer collection %s already disabled",
427                                     layer_collection->scene_collection->name);
428                         return OPERATOR_CANCELLED;
429                 }
430         }
431         else {
432                 if (ELEM(action, ACTION_TOGGLE, ACTION_DISABLE)) {
433                         BKE_collection_disable(view_layer, layer_collection);
434                 }
435                 else { /* ACTION_ENABLE */
436                         BKE_reportf(op->reports, RPT_ERROR, "Layer collection %s already enabled",
437                                     layer_collection->scene_collection->name);
438                         return OPERATOR_CANCELLED;
439                 }
440         }
441
442         DEG_relations_tag_update(bmain);
443         /* TODO(sergey): Use proper flag for tagging here. */
444         DEG_id_tag_update(&scene->id, 0);
445
446         WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
447         WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
448
449         return OPERATOR_FINISHED;
450 }
451
452 void OUTLINER_OT_collection_toggle(wmOperatorType *ot)
453 {
454         PropertyRNA *prop;
455
456         static EnumPropertyItem actions_items[] = {
457                 {ACTION_DISABLE, "DISABLE", 0, "Disable", "Disable selected markers"},
458                 {ACTION_ENABLE, "ENABLE", 0, "Enable", "Enable selected markers"},
459                 {ACTION_TOGGLE, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"},
460                 {0, NULL, 0, NULL, NULL}
461         };
462
463         /* identifiers */
464         ot->name = "Toggle Collection";
465         ot->idname = "OUTLINER_OT_collection_toggle";
466         ot->description = "Deselect collection objects";
467
468         /* api callbacks */
469         ot->exec = collection_toggle_exec;
470
471         /* flags */
472         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
473
474         /* properties */
475         prop = RNA_def_int(ot->srna, "collection_index", -1, -1, INT_MAX, "Collection Index", "Index of collection to toggle", 0, INT_MAX);
476         RNA_def_property_flag(prop, PROP_SKIP_SAVE);
477         prop = RNA_def_enum(ot->srna, "action", actions_items, ACTION_TOGGLE, "Action", "Selection action to execute");
478         RNA_def_property_flag(prop, PROP_SKIP_SAVE);
479 }
480
481 #undef ACTION_TOGGLE
482 #undef ACTION_ENABLE
483 #undef ACTION_DISABLE
484
485 /* -------------------------------------------------------------------- */
486
487 static int stubs_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
488 {
489         TODO_LAYER_OPERATORS;
490         BKE_report(op->reports, RPT_ERROR, "Operator not implemented yet");
491         return OPERATOR_CANCELLED;
492 }
493
494 void OUTLINER_OT_collection_objects_add(wmOperatorType *ot)
495 {
496         /* identifiers */
497         ot->name = "Add Objects";
498         ot->idname = "OUTLINER_OT_collection_objects_add";
499         ot->description = "Add selected objects to collection";
500
501         /* api callbacks */
502         ot->invoke = stubs_invoke;
503
504         /* flags */
505         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
506 }
507
508 void OUTLINER_OT_collection_objects_remove(wmOperatorType *ot)
509 {
510         /* identifiers */
511         ot->name = "Remove Object";
512         ot->idname = "OUTLINER_OT_collection_objects_remove";
513         ot->description = "Remove objects from collection";
514
515         /* api callbacks */
516         ot->invoke = stubs_invoke;
517
518         /* flags */
519         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
520 }
521
522 void OUTLINER_OT_collection_objects_select(wmOperatorType *ot)
523 {
524         /* identifiers */
525         ot->name = "Select Objects";
526         ot->idname = "OUTLINER_OT_collection_objects_select";
527         ot->description = "Select collection objects";
528
529         /* api callbacks */
530         ot->invoke = stubs_invoke;
531
532         /* flags */
533         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
534 }
535
536 void OUTLINER_OT_collection_objects_deselect(wmOperatorType *ot)
537 {
538         /* identifiers */
539         ot->name = "Deselect Objects";
540         ot->idname = "OUTLINER_OT_collection_objects_deselect";
541         ot->description = "Deselect collection objects";
542
543         /* api callbacks */
544         ot->invoke = stubs_invoke;
545
546         /* flags */
547         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
548 }