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