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