Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / render / render_shading.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  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software Foundation,
15  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16  *
17  * The Original Code is Copyright (C) 2009 Blender Foundation.
18  * All rights reserved.
19  *
20  * Contributor(s): Blender Foundation
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file blender/editors/render/render_shading.c
26  *  \ingroup edrend
27  */
28
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_curve_types.h"
35 #include "DNA_lamp_types.h"
36 #include "DNA_lightprobe_types.h"
37 #include "DNA_material_types.h"
38 #include "DNA_node_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_particle_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_space_types.h"
43 #include "DNA_world_types.h"
44
45 #include "BLI_utildefines.h"
46 #include "BLI_listbase.h"
47 #include "BLI_math_vector.h"
48
49 #include "BLT_translation.h"
50
51 #include "BKE_animsys.h"
52 #include "BKE_context.h"
53 #include "BKE_curve.h"
54 #include "BKE_editmesh.h"
55 #include "BKE_font.h"
56 #include "BKE_global.h"
57 #include "BKE_image.h"
58 #include "BKE_layer.h"
59 #include "BKE_library.h"
60 #include "BKE_linestyle.h"
61 #include "BKE_main.h"
62 #include "BKE_material.h"
63 #include "BKE_paint.h"
64 #include "BKE_report.h"
65 #include "BKE_scene.h"
66 #include "BKE_texture.h"
67 #include "BKE_workspace.h"
68 #include "BKE_world.h"
69
70 #include "DEG_depsgraph.h"
71 #include "DEG_depsgraph_build.h"
72
73 #ifdef WITH_FREESTYLE
74 #  include "BKE_freestyle.h"
75 #  include "FRS_freestyle.h"
76 #  include "RNA_enum_types.h"
77 #endif
78
79 #include "RNA_access.h"
80
81 #include "WM_api.h"
82 #include "WM_types.h"
83
84 #include "ED_object.h"
85 #include "ED_curve.h"
86 #include "ED_mesh.h"
87 #include "ED_node.h"
88 #include "ED_render.h"
89 #include "ED_scene.h"
90 #include "ED_screen.h"
91
92 #include "RNA_define.h"
93
94 #include "UI_interface.h"
95
96 #include "RE_pipeline.h"
97
98 #include "engines/eevee/eevee_lightcache.h"
99
100 #include "render_intern.h"  // own include
101
102 /********************** material slot operators *********************/
103
104 static int material_slot_add_exec(bContext *C, wmOperator *UNUSED(op))
105 {
106         Main *bmain = CTX_data_main(C);
107         Object *ob = ED_object_context(C);
108
109         if (!ob)
110                 return OPERATOR_CANCELLED;
111
112         BKE_object_material_slot_add(bmain, ob);
113
114         if (ob->mode & OB_MODE_TEXTURE_PAINT) {
115                 Scene *scene = CTX_data_scene(C);
116                 BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
117                 WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
118         }
119
120         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
121         WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob);
122         WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob);
123
124         return OPERATOR_FINISHED;
125 }
126
127 void OBJECT_OT_material_slot_add(wmOperatorType *ot)
128 {
129         /* identifiers */
130         ot->name = "Add Material Slot";
131         ot->idname = "OBJECT_OT_material_slot_add";
132         ot->description = "Add a new material slot";
133
134         /* api callbacks */
135         ot->exec = material_slot_add_exec;
136         ot->poll = ED_operator_object_active_editable;
137
138         /* flags */
139         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
140 }
141
142 static int material_slot_remove_exec(bContext *C, wmOperator *op)
143 {
144         Object *ob = ED_object_context(C);
145
146         if (!ob)
147                 return OPERATOR_CANCELLED;
148
149         /* Removing material slots in edit mode screws things up, see bug #21822.*/
150         if (ob == CTX_data_edit_object(C)) {
151                 BKE_report(op->reports, RPT_ERROR, "Unable to remove material slot in edit mode");
152                 return OPERATOR_CANCELLED;
153         }
154
155         BKE_object_material_slot_remove(CTX_data_main(C), ob);
156
157         if (ob->mode & OB_MODE_TEXTURE_PAINT) {
158                 Scene *scene = CTX_data_scene(C);
159                 BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
160                 WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
161         }
162
163         DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
164         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
165         WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob);
166         WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob);
167
168         return OPERATOR_FINISHED;
169 }
170
171 void OBJECT_OT_material_slot_remove(wmOperatorType *ot)
172 {
173         /* identifiers */
174         ot->name = "Remove Material Slot";
175         ot->idname = "OBJECT_OT_material_slot_remove";
176         ot->description = "Remove the selected material slot";
177
178         /* api callbacks */
179         ot->exec = material_slot_remove_exec;
180         ot->poll = ED_operator_object_active_editable;
181
182         /* flags */
183         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
184 }
185
186 static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op))
187 {
188         Object *ob = ED_object_context(C);
189         View3D *v3d = CTX_wm_view3d(C);
190
191         if (!ob)
192                 return OPERATOR_CANCELLED;
193
194         if (ob && ob->actcol > 0) {
195                 if (ob->type == OB_MESH) {
196                         BMEditMesh *em = BKE_editmesh_from_object(ob);
197                         BMFace *efa;
198                         BMIter iter;
199
200                         if (em) {
201                                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
202                                         if (BM_elem_flag_test(efa, BM_ELEM_SELECT))
203                                                 efa->mat_nr = ob->actcol - 1;
204                                 }
205                         }
206                 }
207                 else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
208                         Nurb *nu;
209                         ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data);
210
211                         if (nurbs) {
212                                 for (nu = nurbs->first; nu; nu = nu->next) {
213                                         if (ED_curve_nurb_select_check(v3d, nu)) {
214                                                 nu->mat_nr = ob->actcol - 1;
215                                         }
216                                 }
217                         }
218                 }
219                 else if (ob->type == OB_FONT) {
220                         EditFont *ef = ((Curve *)ob->data)->editfont;
221                         int i, selstart, selend;
222
223                         if (ef && BKE_vfont_select_get(ob, &selstart, &selend)) {
224                                 for (i = selstart; i <= selend; i++)
225                                         ef->textbufinfo[i].mat_nr = ob->actcol;
226                         }
227                 }
228         }
229
230         DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
231         WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
232
233         return OPERATOR_FINISHED;
234 }
235
236 void OBJECT_OT_material_slot_assign(wmOperatorType *ot)
237 {
238         /* identifiers */
239         ot->name = "Assign Material Slot";
240         ot->idname = "OBJECT_OT_material_slot_assign";
241         ot->description = "Assign active material slot to selection";
242
243         /* api callbacks */
244         ot->exec = material_slot_assign_exec;
245         ot->poll = ED_operator_object_active_editable;
246
247         /* flags */
248         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
249 }
250
251 static int material_slot_de_select(bContext *C, bool select)
252 {
253         Object *ob = ED_object_context(C);
254
255         if (!ob)
256                 return OPERATOR_CANCELLED;
257
258         if (ob->type == OB_MESH) {
259                 BMEditMesh *em = BKE_editmesh_from_object(ob);
260
261                 if (em) {
262                         EDBM_deselect_by_material(em, ob->actcol - 1, select);
263                 }
264         }
265         else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
266                 ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data);
267                 Nurb *nu;
268                 BPoint *bp;
269                 BezTriple *bezt;
270                 int a;
271
272                 if (nurbs) {
273                         for (nu = nurbs->first; nu; nu = nu->next) {
274                                 if (nu->mat_nr == ob->actcol - 1) {
275                                         if (nu->bezt) {
276                                                 a = nu->pntsu;
277                                                 bezt = nu->bezt;
278                                                 while (a--) {
279                                                         if (bezt->hide == 0) {
280                                                                 if (select) {
281                                                                         bezt->f1 |= SELECT;
282                                                                         bezt->f2 |= SELECT;
283                                                                         bezt->f3 |= SELECT;
284                                                                 }
285                                                                 else {
286                                                                         bezt->f1 &= ~SELECT;
287                                                                         bezt->f2 &= ~SELECT;
288                                                                         bezt->f3 &= ~SELECT;
289                                                                 }
290                                                         }
291                                                         bezt++;
292                                                 }
293                                         }
294                                         else if (nu->bp) {
295                                                 a = nu->pntsu * nu->pntsv;
296                                                 bp = nu->bp;
297                                                 while (a--) {
298                                                         if (bp->hide == 0) {
299                                                                 if (select) bp->f1 |= SELECT;
300                                                                 else bp->f1 &= ~SELECT;
301                                                         }
302                                                         bp++;
303                                                 }
304                                         }
305                                 }
306                         }
307                 }
308         }
309
310         DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE);
311         WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
312
313         return OPERATOR_FINISHED;
314 }
315
316 static int material_slot_select_exec(bContext *C, wmOperator *UNUSED(op))
317 {
318         return material_slot_de_select(C, true);
319 }
320
321 void OBJECT_OT_material_slot_select(wmOperatorType *ot)
322 {
323         /* identifiers */
324         ot->name = "Select Material Slot";
325         ot->idname = "OBJECT_OT_material_slot_select";
326         ot->description = "Select by active material slot";
327
328         /* api callbacks */
329         ot->exec = material_slot_select_exec;
330
331         /* flags */
332         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
333 }
334
335 static int material_slot_deselect_exec(bContext *C, wmOperator *UNUSED(op))
336 {
337         return material_slot_de_select(C, false);
338 }
339
340 void OBJECT_OT_material_slot_deselect(wmOperatorType *ot)
341 {
342         /* identifiers */
343         ot->name = "Deselect Material Slot";
344         ot->idname = "OBJECT_OT_material_slot_deselect";
345         ot->description = "Deselect by active material slot";
346
347         /* api callbacks */
348         ot->exec = material_slot_deselect_exec;
349
350         /* flags */
351         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
352 }
353
354
355 static int material_slot_copy_exec(bContext *C, wmOperator *UNUSED(op))
356 {
357         Main *bmain = CTX_data_main(C);
358         Object *ob = ED_object_context(C);
359         Material ***matar;
360
361         if (!ob || !(matar = give_matarar(ob)))
362                 return OPERATOR_CANCELLED;
363
364         CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects)
365         {
366                 if (ob != ob_iter && give_matarar(ob_iter)) {
367                         if (ob->data != ob_iter->data)
368                                 assign_matarar(bmain, ob_iter, matar, ob->totcol);
369
370                         if (ob_iter->totcol == ob->totcol) {
371                                 ob_iter->actcol = ob->actcol;
372                                 DEG_id_tag_update(&ob_iter->id, OB_RECALC_DATA);
373                                 WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
374                         }
375                 }
376         }
377         CTX_DATA_END;
378
379         return OPERATOR_FINISHED;
380 }
381
382
383 void OBJECT_OT_material_slot_copy(wmOperatorType *ot)
384 {
385         /* identifiers */
386         ot->name = "Copy Material to Selected";
387         ot->idname = "OBJECT_OT_material_slot_copy";
388         ot->description = "Copy material to selected objects";
389
390         /* api callbacks */
391         ot->exec = material_slot_copy_exec;
392
393         /* flags */
394         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
395 }
396
397 static int material_slot_move_exec(bContext *C, wmOperator *op)
398 {
399         Object *ob = ED_object_context(C);
400
401         unsigned int *slot_remap;
402         int index_pair[2];
403
404         int dir = RNA_enum_get(op->ptr, "direction");
405
406         if (!ob || ob->totcol < 2) {
407                 return OPERATOR_CANCELLED;
408         }
409
410         /* up */
411         if (dir == 1 && ob->actcol > 1) {
412                 index_pair[0] = ob->actcol - 2;
413                 index_pair[1] = ob->actcol - 1;
414                 ob->actcol--;
415         }
416         /* down */
417         else if (dir == -1 && ob->actcol < ob->totcol) {
418                 index_pair[0] = ob->actcol - 1;
419                 index_pair[1] = ob->actcol - 0;
420                 ob->actcol++;
421         }
422         else {
423                 return OPERATOR_CANCELLED;
424         }
425
426         slot_remap = MEM_mallocN(sizeof(unsigned int) * ob->totcol, __func__);
427
428         range_vn_u(slot_remap, ob->totcol, 0);
429
430         slot_remap[index_pair[0]] = index_pair[1];
431         slot_remap[index_pair[1]] = index_pair[0];
432
433         BKE_material_remap_object(ob, slot_remap);
434
435         MEM_freeN(slot_remap);
436
437         DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
438         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
439         WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob);
440
441         return OPERATOR_FINISHED;
442 }
443
444 void OBJECT_OT_material_slot_move(wmOperatorType *ot)
445 {
446         static const EnumPropertyItem material_slot_move[] = {
447                 {1, "UP", 0, "Up", ""},
448                 {-1, "DOWN", 0, "Down", ""},
449                 {0, NULL, 0, NULL, NULL}
450         };
451
452         /* identifiers */
453         ot->name = "Move Material";
454         ot->idname = "OBJECT_OT_material_slot_move";
455         ot->description = "Move the active material up/down in the list";
456
457         /* api callbacks */
458         ot->exec = material_slot_move_exec;
459
460         /* flags */
461         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
462
463         RNA_def_enum(ot->srna, "direction", material_slot_move, 0, "Direction",
464                      "Direction to move the active material towards");
465 }
466
467 /********************** new material operator *********************/
468
469 static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
470 {
471         Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
472         Main *bmain = CTX_data_main(C);
473         Object *ob = CTX_data_active_object(C);
474         PointerRNA ptr, idptr;
475         PropertyRNA *prop;
476
477         /* add or copy material */
478         if (ma) {
479                 ma = BKE_material_copy(bmain, ma);
480         }
481         else {
482                 if ((!ob) || (ob->type != OB_GPENCIL)) {
483                         ma = BKE_material_add(bmain, DATA_("Material"));
484                 }
485                 else {
486                         ma = BKE_material_add_gpencil(bmain, DATA_("Material"));
487                 }
488                 ED_node_shader_default(C, &ma->id);
489                 ma->use_nodes = true;
490         }
491
492         /* hook into UI */
493         UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
494
495         if (prop) {
496                 /* when creating new ID blocks, use is already 1, but RNA
497                  * pointer use also increases user, so this compensates it */
498                 id_us_min(&ma->id);
499
500                 RNA_id_pointer_create(&ma->id, &idptr);
501                 RNA_property_pointer_set(&ptr, prop, idptr);
502                 RNA_property_update(C, &ptr, prop);
503         }
504
505         WM_event_add_notifier(C, NC_MATERIAL | NA_ADDED, ma);
506
507         return OPERATOR_FINISHED;
508 }
509
510 void MATERIAL_OT_new(wmOperatorType *ot)
511 {
512         /* identifiers */
513         ot->name = "New Material";
514         ot->idname = "MATERIAL_OT_new";
515         ot->description = "Add a new material";
516
517         /* api callbacks */
518         ot->exec = new_material_exec;
519
520         /* flags */
521         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
522 }
523
524 /********************** new texture operator *********************/
525
526 static int new_texture_exec(bContext *C, wmOperator *UNUSED(op))
527 {
528         Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
529         Main *bmain = CTX_data_main(C);
530         PointerRNA ptr, idptr;
531         PropertyRNA *prop;
532
533         /* add or copy texture */
534         if (tex) {
535                 tex = BKE_texture_copy(bmain, tex);
536         }
537         else {
538                 tex = BKE_texture_add(bmain, DATA_("Texture"));
539         }
540
541         /* hook into UI */
542         UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
543
544         if (prop) {
545                 /* when creating new ID blocks, use is already 1, but RNA
546                  * pointer use also increases user, so this compensates it */
547                 id_us_min(&tex->id);
548
549                 RNA_id_pointer_create(&tex->id, &idptr);
550                 RNA_property_pointer_set(&ptr, prop, idptr);
551                 RNA_property_update(C, &ptr, prop);
552         }
553
554         WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, tex);
555
556         return OPERATOR_FINISHED;
557 }
558
559 void TEXTURE_OT_new(wmOperatorType *ot)
560 {
561         /* identifiers */
562         ot->name = "New Texture";
563         ot->idname = "TEXTURE_OT_new";
564         ot->description = "Add a new texture";
565
566         /* api callbacks */
567         ot->exec = new_texture_exec;
568
569         /* flags */
570         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
571 }
572
573 /********************** new world operator *********************/
574
575 static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
576 {
577         World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
578         Main *bmain = CTX_data_main(C);
579         PointerRNA ptr, idptr;
580         PropertyRNA *prop;
581
582         /* add or copy world */
583         if (wo) {
584                 wo = BKE_world_copy(bmain, wo);
585         }
586         else {
587                 wo = BKE_world_add(bmain, DATA_("World"));
588                 ED_node_shader_default(C, &wo->id);
589                 wo->use_nodes = true;
590         }
591
592         /* hook into UI */
593         UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
594
595         if (prop) {
596                 /* when creating new ID blocks, use is already 1, but RNA
597                  * pointer use also increases user, so this compensates it */
598                 id_us_min(&wo->id);
599
600                 RNA_id_pointer_create(&wo->id, &idptr);
601                 RNA_property_pointer_set(&ptr, prop, idptr);
602                 RNA_property_update(C, &ptr, prop);
603         }
604
605         WM_event_add_notifier(C, NC_WORLD | NA_ADDED, wo);
606
607         return OPERATOR_FINISHED;
608 }
609
610 void WORLD_OT_new(wmOperatorType *ot)
611 {
612         /* identifiers */
613         ot->name = "New World";
614         ot->idname = "WORLD_OT_new";
615         ot->description = "Create a new world Data-Block";
616
617         /* api callbacks */
618         ot->exec = new_world_exec;
619
620         /* flags */
621         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
622 }
623
624 /********************** render layer operators *********************/
625
626 static int view_layer_add_exec(bContext *C, wmOperator *UNUSED(op))
627 {
628         wmWindow *win = CTX_wm_window(C);
629         Scene *scene = CTX_data_scene(C);
630         ViewLayer *view_layer = BKE_view_layer_add(scene, NULL);
631
632         if (win) {
633                 WM_window_set_active_view_layer(win, view_layer);
634         }
635
636         DEG_id_tag_update(&scene->id, 0);
637         DEG_relations_tag_update(CTX_data_main(C));
638         WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
639
640         return OPERATOR_FINISHED;
641 }
642
643 void SCENE_OT_view_layer_add(wmOperatorType *ot)
644 {
645         /* identifiers */
646         ot->name = "Add View Layer";
647         ot->idname = "SCENE_OT_view_layer_add";
648         ot->description = "Add a view layer";
649
650         /* api callbacks */
651         ot->exec = view_layer_add_exec;
652
653         /* flags */
654         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
655 }
656
657 static int view_layer_remove_exec(bContext *C, wmOperator *UNUSED(op))
658 {
659         Main *bmain = CTX_data_main(C);
660         Scene *scene = CTX_data_scene(C);
661         ViewLayer *view_layer = CTX_data_view_layer(C);
662
663         if (!ED_scene_view_layer_delete(bmain, scene, view_layer, NULL)) {
664                 return OPERATOR_CANCELLED;
665         }
666
667         WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
668
669         return OPERATOR_FINISHED;
670 }
671
672 void SCENE_OT_view_layer_remove(wmOperatorType *ot)
673 {
674         /* identifiers */
675         ot->name = "Remove View Layer";
676         ot->idname = "SCENE_OT_view_layer_remove";
677         ot->description = "Remove the selected view layer";
678
679         /* api callbacks */
680         ot->exec = view_layer_remove_exec;
681
682         /* flags */
683         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
684 }
685
686 /********************** light cache operators *********************/
687 enum {
688         LIGHTCACHE_SUBSET_ALL = 0,
689         LIGHTCACHE_SUBSET_DIRTY,
690         LIGHTCACHE_SUBSET_CUBE,
691 };
692
693 static void light_cache_bake_tag_cache(Scene *scene, wmOperator *op)
694 {
695         if (scene->eevee.light_cache != NULL) {
696                 int subset = RNA_enum_get(op->ptr, "subset");
697                 switch (subset) {
698                         case LIGHTCACHE_SUBSET_ALL:
699                                 scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_GRID | LIGHTCACHE_UPDATE_CUBE;
700                                 break;
701                         case LIGHTCACHE_SUBSET_CUBE:
702                                 scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_CUBE;
703                                 break;
704                         case LIGHTCACHE_SUBSET_DIRTY:
705                                 /* Leave tag untouched. */
706                                 break;
707                 }
708         }
709 }
710
711 /* catch esc */
712 static int light_cache_bake_modal(bContext *C, wmOperator *op, const wmEvent *event)
713 {
714         Scene *scene = (Scene *) op->customdata;
715
716         /* no running blender, remove handler and pass through */
717         if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) {
718                 return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
719         }
720
721         /* running render */
722         switch (event->type) {
723                 case ESCKEY:
724                         return OPERATOR_RUNNING_MODAL;
725         }
726         return OPERATOR_PASS_THROUGH;
727 }
728
729 static void light_cache_bake_cancel(bContext *C, wmOperator *op)
730 {
731         wmWindowManager *wm = CTX_wm_manager(C);
732         Scene *scene = (Scene *) op->customdata;
733
734         /* kill on cancel, because job is using op->reports */
735         WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER);
736 }
737
738 /* executes blocking render */
739 static int light_cache_bake_exec(bContext *C, wmOperator *op)
740 {
741         ViewLayer *view_layer = CTX_data_view_layer(C);
742         Main *bmain = CTX_data_main(C);
743         Scene *scene = CTX_data_scene(C);
744
745         G.is_break = false;
746
747         /* TODO abort if selected engine is not eevee. */
748         void *rj = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, false);
749
750         light_cache_bake_tag_cache(scene, op);
751
752         short stop = 0, do_update; float progress; /* Not actually used. */
753         EEVEE_lightbake_job(rj, &stop, &do_update, &progress);
754         EEVEE_lightbake_job_data_free(rj);
755
756         // no redraw needed, we leave state as we entered it
757         ED_update_for_newframe(bmain, CTX_data_depsgraph(C));
758
759         WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
760
761         return OPERATOR_FINISHED;
762 }
763
764 static int light_cache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
765 {
766         wmWindowManager *wm = CTX_wm_manager(C);
767         wmWindow *win = CTX_wm_window(C);
768         ViewLayer *view_layer = CTX_data_view_layer(C);
769         Main *bmain = CTX_data_main(C);
770         Scene *scene = CTX_data_scene(C);
771         int delay = RNA_int_get(op->ptr, "delay");
772
773         wmJob *wm_job = EEVEE_lightbake_job_create(wm, win, bmain, view_layer, scene, delay);
774
775         if (!wm_job) {
776                 return OPERATOR_CANCELLED;
777         }
778
779         /* add modal handler for ESC */
780         WM_event_add_modal_handler(C, op);
781
782         light_cache_bake_tag_cache(scene, op);
783
784         /* store actual owner of job, so modal operator could check for it,
785          * the reason of this is that active scene could change when rendering
786          * several layers from compositor [#31800]
787          */
788         op->customdata = scene;
789
790         WM_jobs_start(wm, wm_job);
791
792         WM_cursor_wait(0);
793
794         return OPERATOR_RUNNING_MODAL;
795 }
796
797 void SCENE_OT_light_cache_bake(wmOperatorType *ot)
798 {
799         static const EnumPropertyItem light_cache_subset_items[] = {
800                 {LIGHTCACHE_SUBSET_ALL, "ALL", 0, "All LightProbes", "Bake both irradiance grids and reflection cubemaps"},
801                 {LIGHTCACHE_SUBSET_DIRTY, "DIRTY", 0, "Dirty Only", "Only bake lightprobes that are marked as dirty"},
802                 {LIGHTCACHE_SUBSET_CUBE, "CUBEMAPS", 0, "Cubemaps Only", "Try to only bake reflection cubemaps if irradiance "
803                                                                      "grids are up to date"},
804                 {0, NULL, 0, NULL, NULL}
805         };
806
807         /* identifiers */
808         ot->name = "Bake Light Cache";
809         ot->idname = "SCENE_OT_light_cache_bake";
810         ot->description = "Bake the active view layer lighting";
811
812         /* api callbacks */
813         ot->invoke = light_cache_bake_invoke;
814         ot->modal = light_cache_bake_modal;
815         ot->cancel = light_cache_bake_cancel;
816         ot->exec = light_cache_bake_exec;
817
818         ot->prop = RNA_def_int(ot->srna, "delay", 0, 0, 2000, "Delay", "Delay in millisecond before baking starts", 0, 2000);
819         RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
820
821         ot->prop = RNA_def_enum(ot->srna, "subset", light_cache_subset_items, 0, "Subset", "Subset of probes to update");
822         RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
823 }
824
825 static bool light_cache_free_poll(bContext *C)
826 {
827         Scene *scene = CTX_data_scene(C);
828
829         return scene->eevee.light_cache;
830 }
831
832 static int light_cache_free_exec(bContext *C, wmOperator *UNUSED(op))
833 {
834         Scene *scene = CTX_data_scene(C);
835
836         /* kill potential bake job first (see T57011) */
837         wmWindowManager *wm = CTX_wm_manager(C);
838         WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_LIGHT_BAKE);
839
840         if (!scene->eevee.light_cache) {
841                 return OPERATOR_CANCELLED;
842         }
843
844         EEVEE_lightcache_free(scene->eevee.light_cache);
845         scene->eevee.light_cache = NULL;
846
847         EEVEE_lightcache_info_update(&scene->eevee);
848
849         DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
850
851         WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
852
853         return OPERATOR_FINISHED;
854 }
855
856 void SCENE_OT_light_cache_free(wmOperatorType *ot)
857 {
858         /* identifiers */
859         ot->name = "Free Light Cache";
860         ot->idname = "SCENE_OT_light_cache_free";
861         ot->description = "Free cached indirect lighting";
862
863         /* api callbacks */
864         ot->exec = light_cache_free_exec;
865         ot->poll = light_cache_free_poll;
866 }
867
868 /********************** render view operators *********************/
869
870 static bool render_view_remove_poll(bContext *C)
871 {
872         Scene *scene = CTX_data_scene(C);
873
874         /* don't allow user to remove "left" and "right" views */
875         return scene->r.actview > 1;
876 }
877
878 static int render_view_add_exec(bContext *C, wmOperator *UNUSED(op))
879 {
880         Scene *scene = CTX_data_scene(C);
881
882         BKE_scene_add_render_view(scene, NULL);
883         scene->r.actview = BLI_listbase_count(&scene->r.views) - 1;
884
885         WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
886
887         return OPERATOR_FINISHED;
888 }
889
890 void SCENE_OT_render_view_add(wmOperatorType *ot)
891 {
892         /* identifiers */
893         ot->name = "Add Render View";
894         ot->idname = "SCENE_OT_render_view_add";
895         ot->description = "Add a render view";
896
897         /* api callbacks */
898         ot->exec = render_view_add_exec;
899
900         /* flags */
901         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
902 }
903
904 static int render_view_remove_exec(bContext *C, wmOperator *UNUSED(op))
905 {
906         Scene *scene = CTX_data_scene(C);
907         SceneRenderView *rv = BLI_findlink(&scene->r.views, scene->r.actview);
908
909         if (!BKE_scene_remove_render_view(scene, rv))
910                 return OPERATOR_CANCELLED;
911
912         WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
913
914         return OPERATOR_FINISHED;
915 }
916
917 void SCENE_OT_render_view_remove(wmOperatorType *ot)
918 {
919         /* identifiers */
920         ot->name = "Remove Render View";
921         ot->idname = "SCENE_OT_render_view_remove";
922         ot->description = "Remove the selected render view";
923
924         /* api callbacks */
925         ot->exec = render_view_remove_exec;
926         ot->poll = render_view_remove_poll;
927
928         /* flags */
929         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
930 }
931
932 #ifdef WITH_FREESTYLE
933
934 static bool freestyle_linestyle_check_report(FreestyleLineSet *lineset, ReportList *reports)
935 {
936         if (!lineset) {
937                 BKE_report(reports, RPT_ERROR, "No active lineset and associated line style to manipulate the modifier");
938                 return false;
939         }
940         if (!lineset->linestyle) {
941                 BKE_report(reports, RPT_ERROR, "The active lineset does not have a line style (indicating data corruption)");
942                 return false;
943         }
944
945         return true;
946 }
947
948 static bool freestyle_active_module_poll(bContext *C)
949 {
950         PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
951         FreestyleModuleConfig *module = ptr.data;
952
953         return module != NULL;
954 }
955
956 static int freestyle_module_add_exec(bContext *C, wmOperator *UNUSED(op))
957 {
958         Scene *scene = CTX_data_scene(C);
959         ViewLayer *view_layer = CTX_data_view_layer(C);
960
961         BKE_freestyle_module_add(&view_layer->freestyle_config);
962
963         WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
964
965         return OPERATOR_FINISHED;
966 }
967
968 void SCENE_OT_freestyle_module_add(wmOperatorType *ot)
969 {
970         /* identifiers */
971         ot->name = "Add Freestyle Module";
972         ot->idname = "SCENE_OT_freestyle_module_add";
973         ot->description = "Add a style module into the list of modules";
974
975         /* api callbacks */
976         ot->exec = freestyle_module_add_exec;
977
978         /* flags */
979         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
980 }
981
982 static int freestyle_module_remove_exec(bContext *C, wmOperator *UNUSED(op))
983 {
984         Scene *scene = CTX_data_scene(C);
985         ViewLayer *view_layer = CTX_data_view_layer(C);
986         PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
987         FreestyleModuleConfig *module = ptr.data;
988
989         BKE_freestyle_module_delete(&view_layer->freestyle_config, module);
990
991         DEG_id_tag_update(&scene->id, 0);
992         WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
993
994         return OPERATOR_FINISHED;
995 }
996
997 void SCENE_OT_freestyle_module_remove(wmOperatorType *ot)
998 {
999         /* identifiers */
1000         ot->name = "Remove Freestyle Module";
1001         ot->idname = "SCENE_OT_freestyle_module_remove";
1002         ot->description = "Remove the style module from the stack";
1003
1004         /* api callbacks */
1005         ot->poll = freestyle_active_module_poll;
1006         ot->exec = freestyle_module_remove_exec;
1007
1008         /* flags */
1009         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1010 }
1011
1012 static int freestyle_module_move_exec(bContext *C, wmOperator *op)
1013 {
1014         Scene *scene = CTX_data_scene(C);
1015         ViewLayer *view_layer = CTX_data_view_layer(C);
1016         PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
1017         FreestyleModuleConfig *module = ptr.data;
1018         int dir = RNA_enum_get(op->ptr, "direction");
1019
1020         if (BKE_freestyle_module_move(&view_layer->freestyle_config, module, dir)) {
1021                 DEG_id_tag_update(&scene->id, 0);
1022                 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1023         }
1024
1025         return OPERATOR_FINISHED;
1026 }
1027
1028 void SCENE_OT_freestyle_module_move(wmOperatorType *ot)
1029 {
1030         static const EnumPropertyItem direction_items[] = {
1031                 {-1, "UP", 0, "Up", ""},
1032                 {1, "DOWN", 0, "Down", ""},
1033                 {0, NULL, 0, NULL, NULL}
1034         };
1035
1036         /* identifiers */
1037         ot->name = "Move Freestyle Module";
1038         ot->idname = "SCENE_OT_freestyle_module_move";
1039         ot->description = "Change the position of the style module within in the list of style modules";
1040
1041         /* api callbacks */
1042         ot->poll = freestyle_active_module_poll;
1043         ot->exec = freestyle_module_move_exec;
1044
1045         /* flags */
1046         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1047
1048         /* props */
1049         RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction",
1050                      "Direction to move the chosen style module towards");
1051 }
1052
1053 static int freestyle_lineset_add_exec(bContext *C, wmOperator *UNUSED(op))
1054 {
1055         Main *bmain = CTX_data_main(C);
1056         Scene *scene = CTX_data_scene(C);
1057         ViewLayer *view_layer = CTX_data_view_layer(C);
1058
1059         BKE_freestyle_lineset_add(bmain, &view_layer->freestyle_config, NULL);
1060
1061         DEG_id_tag_update(&scene->id, 0);
1062         WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1063
1064         return OPERATOR_FINISHED;
1065 }
1066
1067 void SCENE_OT_freestyle_lineset_add(wmOperatorType *ot)
1068 {
1069         /* identifiers */
1070         ot->name = "Add Line Set";
1071         ot->idname = "SCENE_OT_freestyle_lineset_add";
1072         ot->description = "Add a line set into the list of line sets";
1073
1074         /* api callbacks */
1075         ot->exec = freestyle_lineset_add_exec;
1076
1077         /* flags */
1078         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1079 }
1080
1081 static bool freestyle_active_lineset_poll(bContext *C)
1082 {
1083         ViewLayer *view_layer = CTX_data_view_layer(C);
1084
1085         if (!view_layer) {
1086                 return false;
1087         }
1088
1089         return BKE_freestyle_lineset_get_active(&view_layer->freestyle_config) != NULL;
1090 }
1091
1092 static int freestyle_lineset_copy_exec(bContext *C, wmOperator *UNUSED(op))
1093 {
1094         ViewLayer *view_layer = CTX_data_view_layer(C);
1095
1096         FRS_copy_active_lineset(&view_layer->freestyle_config);
1097
1098         return OPERATOR_FINISHED;
1099 }
1100
1101 void SCENE_OT_freestyle_lineset_copy(wmOperatorType *ot)
1102 {
1103         /* identifiers */
1104         ot->name = "Copy Line Set";
1105         ot->idname = "SCENE_OT_freestyle_lineset_copy";
1106         ot->description = "Copy the active line set to a buffer";
1107
1108         /* api callbacks */
1109         ot->exec = freestyle_lineset_copy_exec;
1110         ot->poll = freestyle_active_lineset_poll;
1111
1112         /* flags */
1113         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1114 }
1115
1116 static int freestyle_lineset_paste_exec(bContext *C, wmOperator *UNUSED(op))
1117 {
1118         Scene *scene = CTX_data_scene(C);
1119         ViewLayer *view_layer = CTX_data_view_layer(C);
1120
1121         FRS_paste_active_lineset(&view_layer->freestyle_config);
1122
1123         DEG_id_tag_update(&scene->id, 0);
1124         WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1125
1126         return OPERATOR_FINISHED;
1127 }
1128
1129 void SCENE_OT_freestyle_lineset_paste(wmOperatorType *ot)
1130 {
1131         /* identifiers */
1132         ot->name = "Paste Line Set";
1133         ot->idname = "SCENE_OT_freestyle_lineset_paste";
1134         ot->description = "Paste the buffer content to the active line set";
1135
1136         /* api callbacks */
1137         ot->exec = freestyle_lineset_paste_exec;
1138         ot->poll = freestyle_active_lineset_poll;
1139
1140         /* flags */
1141         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1142 }
1143
1144 static int freestyle_lineset_remove_exec(bContext *C, wmOperator *UNUSED(op))
1145 {
1146         Scene *scene = CTX_data_scene(C);
1147         ViewLayer *view_layer = CTX_data_view_layer(C);
1148
1149         FRS_delete_active_lineset(&view_layer->freestyle_config);
1150
1151         DEG_id_tag_update(&scene->id, 0);
1152         WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1153
1154         return OPERATOR_FINISHED;
1155 }
1156
1157 void SCENE_OT_freestyle_lineset_remove(wmOperatorType *ot)
1158 {
1159         /* identifiers */
1160         ot->name = "Remove Line Set";
1161         ot->idname = "SCENE_OT_freestyle_lineset_remove";
1162         ot->description = "Remove the active line set from the list of line sets";
1163
1164         /* api callbacks */
1165         ot->exec = freestyle_lineset_remove_exec;
1166         ot->poll = freestyle_active_lineset_poll;
1167
1168         /* flags */
1169         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1170 }
1171
1172 static int freestyle_lineset_move_exec(bContext *C, wmOperator *op)
1173 {
1174         Scene *scene = CTX_data_scene(C);
1175         ViewLayer *view_layer = CTX_data_view_layer(C);
1176         int dir = RNA_enum_get(op->ptr, "direction");
1177
1178         if (FRS_move_active_lineset(&view_layer->freestyle_config, dir)) {
1179                 DEG_id_tag_update(&scene->id, 0);
1180                 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1181         }
1182
1183         return OPERATOR_FINISHED;
1184 }
1185
1186 void SCENE_OT_freestyle_lineset_move(wmOperatorType *ot)
1187 {
1188         static const EnumPropertyItem direction_items[] = {
1189                 {-1, "UP", 0, "Up", ""},
1190                 {1, "DOWN", 0, "Down", ""},
1191                 {0, NULL, 0, NULL, NULL}
1192         };
1193
1194         /* identifiers */
1195         ot->name = "Move Line Set";
1196         ot->idname = "SCENE_OT_freestyle_lineset_move";
1197         ot->description = "Change the position of the active line set within the list of line sets";
1198
1199         /* api callbacks */
1200         ot->exec = freestyle_lineset_move_exec;
1201         ot->poll = freestyle_active_lineset_poll;
1202
1203         /* flags */
1204         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1205
1206         /* props */
1207         RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction",
1208                      "Direction to move the active line set towards");
1209 }
1210
1211 static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op)
1212 {
1213         Main *bmain = CTX_data_main(C);
1214         ViewLayer *view_layer = CTX_data_view_layer(C);
1215         FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1216
1217         if (!lineset) {
1218                 BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to");
1219                 return OPERATOR_CANCELLED;
1220         }
1221         if (lineset->linestyle) {
1222                 id_us_min(&lineset->linestyle->id);
1223                 lineset->linestyle = BKE_linestyle_copy(bmain, lineset->linestyle);
1224         }
1225         else {
1226                 lineset->linestyle = BKE_linestyle_new(bmain, "LineStyle");
1227         }
1228         DEG_id_tag_update(&lineset->linestyle->id, 0);
1229         WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1230
1231         return OPERATOR_FINISHED;
1232 }
1233
1234 void SCENE_OT_freestyle_linestyle_new(wmOperatorType *ot)
1235 {
1236         /* identifiers */
1237         ot->name = "New Line Style";
1238         ot->idname = "SCENE_OT_freestyle_linestyle_new";
1239         ot->description = "Create a new line style, reusable by multiple line sets";
1240
1241         /* api callbacks */
1242         ot->exec = freestyle_linestyle_new_exec;
1243         ot->poll = freestyle_active_lineset_poll;
1244
1245         /* flags */
1246         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1247 }
1248
1249 static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op)
1250 {
1251         ViewLayer *view_layer = CTX_data_view_layer(C);
1252         FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1253         int type = RNA_enum_get(op->ptr, "type");
1254
1255         if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1256                 return OPERATOR_CANCELLED;
1257         }
1258
1259         if (BKE_linestyle_color_modifier_add(lineset->linestyle, NULL, type) == NULL) {
1260                 BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type");
1261                 return OPERATOR_CANCELLED;
1262         }
1263         DEG_id_tag_update(&lineset->linestyle->id, 0);
1264         WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1265
1266         return OPERATOR_FINISHED;
1267 }
1268
1269 void SCENE_OT_freestyle_color_modifier_add(wmOperatorType *ot)
1270 {
1271         /* identifiers */
1272         ot->name = "Add Line Color Modifier";
1273         ot->idname = "SCENE_OT_freestyle_color_modifier_add";
1274         ot->description = "Add a line color modifier to the line style associated with the active lineset";
1275
1276         /* api callbacks */
1277         ot->invoke = WM_menu_invoke;
1278         ot->exec = freestyle_color_modifier_add_exec;
1279         ot->poll = freestyle_active_lineset_poll;
1280
1281         /* flags */
1282         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1283
1284         /* properties */
1285         ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_color_modifier_type_items, 0, "Type", "");
1286 }
1287
1288 static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op)
1289 {
1290         ViewLayer *view_layer = CTX_data_view_layer(C);
1291         FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1292         int type = RNA_enum_get(op->ptr, "type");
1293
1294         if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1295                 return OPERATOR_CANCELLED;
1296         }
1297
1298         if (BKE_linestyle_alpha_modifier_add(lineset->linestyle, NULL, type) == NULL) {
1299                 BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type");
1300                 return OPERATOR_CANCELLED;
1301         }
1302         DEG_id_tag_update(&lineset->linestyle->id, 0);
1303         WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1304
1305         return OPERATOR_FINISHED;
1306 }
1307
1308 void SCENE_OT_freestyle_alpha_modifier_add(wmOperatorType *ot)
1309 {
1310         /* identifiers */
1311         ot->name = "Add Alpha Transparency Modifier";
1312         ot->idname = "SCENE_OT_freestyle_alpha_modifier_add";
1313         ot->description = "Add an alpha transparency modifier to the line style associated with the active lineset";
1314
1315         /* api callbacks */
1316         ot->invoke = WM_menu_invoke;
1317         ot->exec = freestyle_alpha_modifier_add_exec;
1318         ot->poll = freestyle_active_lineset_poll;
1319
1320         /* flags */
1321         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1322
1323         /* properties */
1324         ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_alpha_modifier_type_items, 0, "Type", "");
1325 }
1326
1327 static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op)
1328 {
1329         ViewLayer *view_layer = CTX_data_view_layer(C);
1330         FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1331         int type = RNA_enum_get(op->ptr, "type");
1332
1333         if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1334                 return OPERATOR_CANCELLED;
1335         }
1336
1337         if (BKE_linestyle_thickness_modifier_add(lineset->linestyle, NULL, type) == NULL) {
1338                 BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type");
1339                 return OPERATOR_CANCELLED;
1340         }
1341         DEG_id_tag_update(&lineset->linestyle->id, 0);
1342         WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1343
1344         return OPERATOR_FINISHED;
1345 }
1346
1347 void SCENE_OT_freestyle_thickness_modifier_add(wmOperatorType *ot)
1348 {
1349         /* identifiers */
1350         ot->name = "Add Line Thickness Modifier";
1351         ot->idname = "SCENE_OT_freestyle_thickness_modifier_add";
1352         ot->description = "Add a line thickness modifier to the line style associated with the active lineset";
1353
1354         /* api callbacks */
1355         ot->invoke = WM_menu_invoke;
1356         ot->exec = freestyle_thickness_modifier_add_exec;
1357         ot->poll = freestyle_active_lineset_poll;
1358
1359         /* flags */
1360         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1361
1362         /* properties */
1363         ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_thickness_modifier_type_items, 0, "Type", "");
1364 }
1365
1366 static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op)
1367 {
1368         ViewLayer *view_layer = CTX_data_view_layer(C);
1369         FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1370         int type = RNA_enum_get(op->ptr, "type");
1371
1372         if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1373                 return OPERATOR_CANCELLED;
1374         }
1375
1376         if (BKE_linestyle_geometry_modifier_add(lineset->linestyle, NULL, type) == NULL) {
1377                 BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type");
1378                 return OPERATOR_CANCELLED;
1379         }
1380         DEG_id_tag_update(&lineset->linestyle->id, 0);
1381         WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1382
1383         return OPERATOR_FINISHED;
1384 }
1385
1386 void SCENE_OT_freestyle_geometry_modifier_add(wmOperatorType *ot)
1387 {
1388         /* identifiers */
1389         ot->name = "Add Stroke Geometry Modifier";
1390         ot->idname = "SCENE_OT_freestyle_geometry_modifier_add";
1391         ot->description = "Add a stroke geometry modifier to the line style associated with the active lineset";
1392
1393         /* api callbacks */
1394         ot->invoke = WM_menu_invoke;
1395         ot->exec = freestyle_geometry_modifier_add_exec;
1396         ot->poll = freestyle_active_lineset_poll;
1397
1398         /* flags */
1399         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1400
1401         /* properties */
1402         ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_geometry_modifier_type_items, 0, "Type", "");
1403 }
1404
1405 static int freestyle_get_modifier_type(PointerRNA *ptr)
1406 {
1407         if (RNA_struct_is_a(ptr->type, &RNA_LineStyleColorModifier))
1408                 return LS_MODIFIER_TYPE_COLOR;
1409         else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleAlphaModifier))
1410                 return LS_MODIFIER_TYPE_ALPHA;
1411         else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleThicknessModifier))
1412                 return LS_MODIFIER_TYPE_THICKNESS;
1413         else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleGeometryModifier))
1414                 return LS_MODIFIER_TYPE_GEOMETRY;
1415         return -1;
1416 }
1417
1418 static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op)
1419 {
1420         ViewLayer *view_layer = CTX_data_view_layer(C);
1421         FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1422         PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
1423         LineStyleModifier *modifier = ptr.data;
1424
1425         if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1426                 return OPERATOR_CANCELLED;
1427         }
1428
1429         switch (freestyle_get_modifier_type(&ptr)) {
1430                 case LS_MODIFIER_TYPE_COLOR:
1431                         BKE_linestyle_color_modifier_remove(lineset->linestyle, modifier);
1432                         break;
1433                 case LS_MODIFIER_TYPE_ALPHA:
1434                         BKE_linestyle_alpha_modifier_remove(lineset->linestyle, modifier);
1435                         break;
1436                 case LS_MODIFIER_TYPE_THICKNESS:
1437                         BKE_linestyle_thickness_modifier_remove(lineset->linestyle, modifier);
1438                         break;
1439                 case LS_MODIFIER_TYPE_GEOMETRY:
1440                         BKE_linestyle_geometry_modifier_remove(lineset->linestyle, modifier);
1441                         break;
1442                 default:
1443                         BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
1444                         return OPERATOR_CANCELLED;
1445         }
1446         DEG_id_tag_update(&lineset->linestyle->id, 0);
1447         WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1448
1449         return OPERATOR_FINISHED;
1450 }
1451
1452 void SCENE_OT_freestyle_modifier_remove(wmOperatorType *ot)
1453 {
1454         /* identifiers */
1455         ot->name = "Remove Modifier";
1456         ot->idname = "SCENE_OT_freestyle_modifier_remove";
1457         ot->description = "Remove the modifier from the list of modifiers";
1458
1459         /* api callbacks */
1460         ot->exec = freestyle_modifier_remove_exec;
1461         ot->poll = freestyle_active_lineset_poll;
1462
1463         /* flags */
1464         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1465 }
1466
1467 static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op)
1468 {
1469         ViewLayer *view_layer = CTX_data_view_layer(C);
1470         FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1471         PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
1472         LineStyleModifier *modifier = ptr.data;
1473
1474         if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1475                 return OPERATOR_CANCELLED;
1476         }
1477
1478         switch (freestyle_get_modifier_type(&ptr)) {
1479                 case LS_MODIFIER_TYPE_COLOR:
1480                         BKE_linestyle_color_modifier_copy(lineset->linestyle, modifier, 0);
1481                         break;
1482                 case LS_MODIFIER_TYPE_ALPHA:
1483                         BKE_linestyle_alpha_modifier_copy(lineset->linestyle, modifier, 0);
1484                         break;
1485                 case LS_MODIFIER_TYPE_THICKNESS:
1486                         BKE_linestyle_thickness_modifier_copy(lineset->linestyle, modifier, 0);
1487                         break;
1488                 case LS_MODIFIER_TYPE_GEOMETRY:
1489                         BKE_linestyle_geometry_modifier_copy(lineset->linestyle, modifier, 0);
1490                         break;
1491                 default:
1492                         BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
1493                         return OPERATOR_CANCELLED;
1494         }
1495         DEG_id_tag_update(&lineset->linestyle->id, 0);
1496         WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1497
1498         return OPERATOR_FINISHED;
1499 }
1500
1501 void SCENE_OT_freestyle_modifier_copy(wmOperatorType *ot)
1502 {
1503         /* identifiers */
1504         ot->name = "Copy Modifier";
1505         ot->idname = "SCENE_OT_freestyle_modifier_copy";
1506         ot->description = "Duplicate the modifier within the list of modifiers";
1507
1508         /* api callbacks */
1509         ot->exec = freestyle_modifier_copy_exec;
1510         ot->poll = freestyle_active_lineset_poll;
1511
1512         /* flags */
1513         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1514 }
1515
1516 static int freestyle_modifier_move_exec(bContext *C, wmOperator *op)
1517 {
1518         ViewLayer *view_layer = CTX_data_view_layer(C);
1519         FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1520         PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
1521         LineStyleModifier *modifier = ptr.data;
1522         int dir = RNA_enum_get(op->ptr, "direction");
1523         bool changed = false;
1524
1525         if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1526                 return OPERATOR_CANCELLED;
1527         }
1528
1529         switch (freestyle_get_modifier_type(&ptr)) {
1530                 case LS_MODIFIER_TYPE_COLOR:
1531                         changed = BKE_linestyle_color_modifier_move(lineset->linestyle, modifier, dir);
1532                         break;
1533                 case LS_MODIFIER_TYPE_ALPHA:
1534                         changed = BKE_linestyle_alpha_modifier_move(lineset->linestyle, modifier, dir);
1535                         break;
1536                 case LS_MODIFIER_TYPE_THICKNESS:
1537                         changed = BKE_linestyle_thickness_modifier_move(lineset->linestyle, modifier, dir);
1538                         break;
1539                 case LS_MODIFIER_TYPE_GEOMETRY:
1540                         changed = BKE_linestyle_geometry_modifier_move(lineset->linestyle, modifier, dir);
1541                         break;
1542                 default:
1543                         BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
1544                         return OPERATOR_CANCELLED;
1545         }
1546
1547         if (changed) {
1548                 DEG_id_tag_update(&lineset->linestyle->id, 0);
1549                 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1550         }
1551
1552         return OPERATOR_FINISHED;
1553 }
1554
1555 void SCENE_OT_freestyle_modifier_move(wmOperatorType *ot)
1556 {
1557         static const EnumPropertyItem direction_items[] = {
1558                 {-1, "UP", 0, "Up", ""},
1559                 {1, "DOWN", 0, "Down", ""},
1560                 {0, NULL, 0, NULL, NULL}
1561         };
1562
1563         /* identifiers */
1564         ot->name = "Move Modifier";
1565         ot->idname = "SCENE_OT_freestyle_modifier_move";
1566         ot->description = "Move the modifier within the list of modifiers";
1567
1568         /* api callbacks */
1569         ot->exec = freestyle_modifier_move_exec;
1570         ot->poll = freestyle_active_lineset_poll;
1571
1572         /* flags */
1573         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1574
1575         /* props */
1576         RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction",
1577                      "Direction to move the chosen modifier towards");
1578 }
1579
1580 static int freestyle_stroke_material_create_exec(bContext *C, wmOperator *op)
1581 {
1582         Main *bmain = CTX_data_main(C);
1583         ViewLayer *view_layer = CTX_data_view_layer(C);
1584         FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(view_layer);
1585
1586         if (!linestyle) {
1587                 BKE_report(op->reports, RPT_ERROR, "No active line style in the current scene");
1588                 return OPERATOR_CANCELLED;
1589         }
1590
1591         FRS_create_stroke_material(bmain, linestyle);
1592
1593         return OPERATOR_FINISHED;
1594 }
1595
1596 void SCENE_OT_freestyle_stroke_material_create(wmOperatorType *ot)
1597 {
1598         /* identifiers */
1599         ot->name = "Create Freestyle Stroke Material";
1600         ot->idname = "SCENE_OT_freestyle_stroke_material_create";
1601         ot->description = "Create Freestyle stroke material for testing";
1602
1603         /* api callbacks */
1604         ot->exec = freestyle_stroke_material_create_exec;
1605
1606         /* flags */
1607         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1608 }
1609
1610 #endif /* WITH_FREESTYLE */
1611
1612 static int texture_slot_move_exec(bContext *C, wmOperator *op)
1613 {
1614         ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
1615
1616         if (id) {
1617                 MTex **mtex_ar, *mtexswap;
1618                 short act;
1619                 int type = RNA_enum_get(op->ptr, "type");
1620                 struct AnimData *adt = BKE_animdata_from_id(id);
1621
1622                 give_active_mtex(id, &mtex_ar, &act);
1623
1624                 if (type == -1) { /* Up */
1625                         if (act > 0) {
1626                                 mtexswap = mtex_ar[act];
1627                                 mtex_ar[act] = mtex_ar[act - 1];
1628                                 mtex_ar[act - 1] = mtexswap;
1629
1630                                 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act - 1, -1, 0);
1631                                 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act - 1, 0);
1632                                 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0);
1633
1634                                 set_active_mtex(id, act - 1);
1635                         }
1636                 }
1637                 else { /* Down */
1638                         if (act < MAX_MTEX - 1) {
1639                                 mtexswap = mtex_ar[act];
1640                                 mtex_ar[act] = mtex_ar[act + 1];
1641                                 mtex_ar[act + 1] = mtexswap;
1642
1643                                 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act + 1, -1, 0);
1644                                 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act + 1, 0);
1645                                 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0);
1646
1647                                 set_active_mtex(id, act + 1);
1648                         }
1649                 }
1650
1651                 DEG_id_tag_update(id, 0);
1652                 WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C));
1653         }
1654
1655         return OPERATOR_FINISHED;
1656 }
1657
1658 void TEXTURE_OT_slot_move(wmOperatorType *ot)
1659 {
1660         static const EnumPropertyItem slot_move[] = {
1661                 {-1, "UP", 0, "Up", ""},
1662                 {1, "DOWN", 0, "Down", ""},
1663                 {0, NULL, 0, NULL, NULL}
1664         };
1665
1666         /* identifiers */
1667         ot->name = "Move Texture Slot";
1668         ot->idname = "TEXTURE_OT_slot_move";
1669         ot->description = "Move texture slots up and down";
1670
1671         /* api callbacks */
1672         ot->exec = texture_slot_move_exec;
1673
1674         /* flags */
1675         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1676
1677         RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
1678 }
1679
1680
1681
1682 /********************** material operators *********************/
1683
1684 /* material copy/paste */
1685 static int copy_material_exec(bContext *C, wmOperator *UNUSED(op))
1686 {
1687         Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
1688
1689         if (ma == NULL)
1690                 return OPERATOR_CANCELLED;
1691
1692         copy_matcopybuf(CTX_data_main(C), ma);
1693
1694         return OPERATOR_FINISHED;
1695 }
1696
1697 void MATERIAL_OT_copy(wmOperatorType *ot)
1698 {
1699         /* identifiers */
1700         ot->name = "Copy Material";
1701         ot->idname = "MATERIAL_OT_copy";
1702         ot->description = "Copy the material settings and nodes";
1703
1704         /* api callbacks */
1705         ot->exec = copy_material_exec;
1706
1707         /* flags */
1708         ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL; /* no undo needed since no changes are made to the material */
1709 }
1710
1711 static int paste_material_exec(bContext *C, wmOperator *UNUSED(op))
1712 {
1713         Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
1714
1715         if (ma == NULL)
1716                 return OPERATOR_CANCELLED;
1717
1718         paste_matcopybuf(CTX_data_main(C), ma);
1719
1720         WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma);
1721
1722         return OPERATOR_FINISHED;
1723 }
1724
1725 void MATERIAL_OT_paste(wmOperatorType *ot)
1726 {
1727         /* identifiers */
1728         ot->name = "Paste Material";
1729         ot->idname = "MATERIAL_OT_paste";
1730         ot->description = "Paste the material settings and nodes";
1731
1732         /* api callbacks */
1733         ot->exec = paste_material_exec;
1734
1735         /* flags */
1736         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1737 }
1738
1739
1740 static short mtexcopied = 0; /* must be reset on file load */
1741 static MTex mtexcopybuf;
1742
1743 void ED_render_clear_mtex_copybuf(void)
1744 {   /* use for file reload */
1745         mtexcopied = 0;
1746 }
1747
1748 static void copy_mtex_copybuf(ID *id)
1749 {
1750         MTex **mtex = NULL;
1751
1752         switch (GS(id->name)) {
1753                 case ID_PA:
1754                         mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
1755                         break;
1756                 case ID_LS:
1757                         mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
1758                         break;
1759                 default:
1760                         break;
1761         }
1762
1763         if (mtex && *mtex) {
1764                 memcpy(&mtexcopybuf, *mtex, sizeof(MTex));
1765                 mtexcopied = 1;
1766         }
1767         else {
1768                 mtexcopied = 0;
1769         }
1770 }
1771
1772 static void paste_mtex_copybuf(ID *id)
1773 {
1774         MTex **mtex = NULL;
1775
1776         if (mtexcopied == 0 || mtexcopybuf.tex == NULL)
1777                 return;
1778
1779         switch (GS(id->name)) {
1780                 case ID_PA:
1781                         mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
1782                         break;
1783                 case ID_LS:
1784                         mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
1785                         break;
1786                 default:
1787                         BLI_assert(!"invalid id type");
1788                         return;
1789         }
1790
1791         if (mtex) {
1792                 if (*mtex == NULL) {
1793                         *mtex = MEM_mallocN(sizeof(MTex), "mtex copy");
1794                 }
1795                 else if ((*mtex)->tex) {
1796                         id_us_min(&(*mtex)->tex->id);
1797                 }
1798
1799                 memcpy(*mtex, &mtexcopybuf, sizeof(MTex));
1800
1801                 id_us_plus((ID *)mtexcopybuf.tex);
1802         }
1803 }
1804
1805
1806 static int copy_mtex_exec(bContext *C, wmOperator *UNUSED(op))
1807 {
1808         ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
1809
1810         if (id == NULL) {
1811                 /* copying empty slot */
1812                 ED_render_clear_mtex_copybuf();
1813                 return OPERATOR_CANCELLED;
1814         }
1815
1816         copy_mtex_copybuf(id);
1817
1818         return OPERATOR_FINISHED;
1819 }
1820
1821 static bool copy_mtex_poll(bContext *C)
1822 {
1823         ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
1824
1825         return (id != NULL);
1826 }
1827
1828 void TEXTURE_OT_slot_copy(wmOperatorType *ot)
1829 {
1830         /* identifiers */
1831         ot->name = "Copy Texture Slot Settings";
1832         ot->idname = "TEXTURE_OT_slot_copy";
1833         ot->description = "Copy the material texture settings and nodes";
1834
1835         /* api callbacks */
1836         ot->exec = copy_mtex_exec;
1837         ot->poll = copy_mtex_poll;
1838
1839         /* flags */
1840         ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL; /* no undo needed since no changes are made to the mtex */
1841 }
1842
1843 static int paste_mtex_exec(bContext *C, wmOperator *UNUSED(op))
1844 {
1845         ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
1846
1847         if (id == NULL) {
1848                 Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
1849                 Lamp *la = CTX_data_pointer_get_type(C, "light", &RNA_Light).data;
1850                 World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
1851                 ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data;
1852                 FreestyleLineStyle *linestyle = CTX_data_pointer_get_type(C, "line_style", &RNA_FreestyleLineStyle).data;
1853
1854                 if (ma)
1855                         id = &ma->id;
1856                 else if (la)
1857                         id = &la->id;
1858                 else if (wo)
1859                         id = &wo->id;
1860                 else if (psys)
1861                         id = &psys->part->id;
1862                 else if (linestyle)
1863                         id = &linestyle->id;
1864
1865                 if (id == NULL)
1866                         return OPERATOR_CANCELLED;
1867         }
1868
1869         paste_mtex_copybuf(id);
1870
1871         WM_event_add_notifier(C, NC_TEXTURE | ND_SHADING_LINKS, NULL);
1872
1873         return OPERATOR_FINISHED;
1874 }
1875
1876 void TEXTURE_OT_slot_paste(wmOperatorType *ot)
1877 {
1878         /* identifiers */
1879         ot->name = "Paste Texture Slot Settings";
1880         ot->idname = "TEXTURE_OT_slot_paste";
1881         ot->description = "Copy the texture settings and nodes";
1882
1883         /* api callbacks */
1884         ot->exec = paste_mtex_exec;
1885
1886         /* flags */
1887         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1888 }