Cleanup: misc spelling fixes
[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 that's 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 static int material_slot_remove_unused_exec(bContext *C, wmOperator *op)
553 {
554   Object *ob = CTX_data_active_object(C);
555
556   if (!ob) {
557     return OPERATOR_CANCELLED;
558   }
559
560   /* Removing material slots in edit mode screws things up, see bug #21822.*/
561   if (ob == CTX_data_edit_object(C)) {
562     BKE_report(op->reports, RPT_ERROR, "Unable to remove material slot in edit mode");
563     return OPERATOR_CANCELLED;
564   }
565
566   int actcol = ob->actcol;
567
568   int removed = 0;
569   for (int slot = 1; slot <= ob->totcol; slot++) {
570     while (slot <= ob->totcol && !BKE_object_material_slot_used(ob->data, slot)) {
571       ob->actcol = slot;
572       BKE_object_material_slot_remove(CTX_data_main(C), ob);
573
574       if (actcol >= slot) {
575         actcol--;
576       }
577
578       removed++;
579     }
580   }
581
582   ob->actcol = actcol;
583
584   if (!removed) {
585     return OPERATOR_CANCELLED;
586   }
587
588   BKE_reportf(op->reports, RPT_INFO, "Removed %d slots", removed);
589
590   if (ob->mode & OB_MODE_TEXTURE_PAINT) {
591     Scene *scene = CTX_data_scene(C);
592     BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
593     WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
594   }
595
596   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
597   WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
598   WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob);
599   WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob);
600
601   return OPERATOR_FINISHED;
602 }
603
604 void OBJECT_OT_material_slot_remove_unused(wmOperatorType *ot)
605 {
606   /* identifiers */
607   ot->name = "Remove Unused Slots";
608   ot->idname = "OBJECT_OT_material_slot_remove_unused";
609   ot->description = "Remove unused material slots";
610
611   /* api callbacks */
612   ot->exec = material_slot_remove_unused_exec;
613   ot->poll = ED_operator_object_active_editable;
614
615   /* flags */
616   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
617 }
618
619 /********************** new material operator *********************/
620
621 static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
622 {
623   Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
624   Main *bmain = CTX_data_main(C);
625   PointerRNA ptr, idptr;
626   PropertyRNA *prop;
627
628   /* hook into UI */
629   UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
630
631   Object *ob = (prop && RNA_struct_is_a(ptr.type, &RNA_Object)) ? ptr.data : NULL;
632
633   /* add or copy material */
634   if (ma) {
635     Material *new_ma = NULL;
636     BKE_id_copy_ex(bmain, &ma->id, (ID **)&new_ma, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS);
637     ma = new_ma;
638   }
639   else {
640     const char *name = DATA_("Material");
641     if (!(ob != NULL && ob->type == OB_GPENCIL)) {
642       ma = BKE_material_add(bmain, name);
643     }
644     else {
645       ma = BKE_material_add_gpencil(bmain, name);
646     }
647     ED_node_shader_default(C, &ma->id);
648     ma->use_nodes = true;
649   }
650
651   if (prop) {
652     if (ob != NULL) {
653       /* Add slot follows user-preferences for creating new slots,
654        * RNA pointer assignment doesn't, see: T60014. */
655       if (give_current_material_p(ob, ob->actcol) == NULL) {
656         BKE_object_material_slot_add(bmain, ob);
657       }
658     }
659
660     /* when creating new ID blocks, use is already 1, but RNA
661      * pointer use also increases user, so this compensates it */
662     id_us_min(&ma->id);
663
664     RNA_id_pointer_create(&ma->id, &idptr);
665     RNA_property_pointer_set(&ptr, prop, idptr, NULL);
666     RNA_property_update(C, &ptr, prop);
667   }
668
669   WM_event_add_notifier(C, NC_MATERIAL | NA_ADDED, ma);
670
671   return OPERATOR_FINISHED;
672 }
673
674 void MATERIAL_OT_new(wmOperatorType *ot)
675 {
676   /* identifiers */
677   ot->name = "New Material";
678   ot->idname = "MATERIAL_OT_new";
679   ot->description = "Add a new material";
680
681   /* api callbacks */
682   ot->exec = new_material_exec;
683
684   /* flags */
685   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
686 }
687
688 /********************** new texture operator *********************/
689
690 static int new_texture_exec(bContext *C, wmOperator *UNUSED(op))
691 {
692   Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
693   Main *bmain = CTX_data_main(C);
694   PointerRNA ptr, idptr;
695   PropertyRNA *prop;
696
697   /* add or copy texture */
698   if (tex) {
699     tex = BKE_texture_copy(bmain, tex);
700   }
701   else {
702     tex = BKE_texture_add(bmain, DATA_("Texture"));
703   }
704
705   /* hook into UI */
706   UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
707
708   if (prop) {
709     /* when creating new ID blocks, use is already 1, but RNA
710      * pointer use also increases user, so this compensates it */
711     id_us_min(&tex->id);
712
713     RNA_id_pointer_create(&tex->id, &idptr);
714     RNA_property_pointer_set(&ptr, prop, idptr, NULL);
715     RNA_property_update(C, &ptr, prop);
716   }
717
718   WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, tex);
719
720   return OPERATOR_FINISHED;
721 }
722
723 void TEXTURE_OT_new(wmOperatorType *ot)
724 {
725   /* identifiers */
726   ot->name = "New Texture";
727   ot->idname = "TEXTURE_OT_new";
728   ot->description = "Add a new texture";
729
730   /* api callbacks */
731   ot->exec = new_texture_exec;
732
733   /* flags */
734   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
735 }
736
737 /********************** new world operator *********************/
738
739 static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
740 {
741   World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
742   Main *bmain = CTX_data_main(C);
743   PointerRNA ptr, idptr;
744   PropertyRNA *prop;
745
746   /* add or copy world */
747   if (wo) {
748     wo = BKE_world_copy(bmain, wo);
749   }
750   else {
751     wo = BKE_world_add(bmain, DATA_("World"));
752     ED_node_shader_default(C, &wo->id);
753     wo->use_nodes = true;
754   }
755
756   /* hook into UI */
757   UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
758
759   if (prop) {
760     /* when creating new ID blocks, use is already 1, but RNA
761      * pointer use also increases user, so this compensates it */
762     id_us_min(&wo->id);
763
764     RNA_id_pointer_create(&wo->id, &idptr);
765     RNA_property_pointer_set(&ptr, prop, idptr, NULL);
766     RNA_property_update(C, &ptr, prop);
767   }
768
769   WM_event_add_notifier(C, NC_WORLD | NA_ADDED, wo);
770
771   return OPERATOR_FINISHED;
772 }
773
774 void WORLD_OT_new(wmOperatorType *ot)
775 {
776   /* identifiers */
777   ot->name = "New World";
778   ot->idname = "WORLD_OT_new";
779   ot->description = "Create a new world Data-Block";
780
781   /* api callbacks */
782   ot->exec = new_world_exec;
783
784   /* flags */
785   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
786 }
787
788 /********************** render layer operators *********************/
789
790 static int view_layer_add_exec(bContext *C, wmOperator *UNUSED(op))
791 {
792   wmWindow *win = CTX_wm_window(C);
793   Scene *scene = CTX_data_scene(C);
794   ViewLayer *view_layer = BKE_view_layer_add(scene, NULL);
795
796   if (win) {
797     WM_window_set_active_view_layer(win, view_layer);
798   }
799
800   DEG_id_tag_update(&scene->id, 0);
801   DEG_relations_tag_update(CTX_data_main(C));
802   WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
803
804   return OPERATOR_FINISHED;
805 }
806
807 void SCENE_OT_view_layer_add(wmOperatorType *ot)
808 {
809   /* identifiers */
810   ot->name = "Add View Layer";
811   ot->idname = "SCENE_OT_view_layer_add";
812   ot->description = "Add a view layer";
813
814   /* api callbacks */
815   ot->exec = view_layer_add_exec;
816
817   /* flags */
818   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
819 }
820
821 static bool view_layer_remove_poll(bContext *C)
822 {
823   Scene *scene = CTX_data_scene(C);
824   return (scene->view_layers.first != scene->view_layers.last);
825 }
826
827 static int view_layer_remove_exec(bContext *C, wmOperator *UNUSED(op))
828 {
829   Main *bmain = CTX_data_main(C);
830   Scene *scene = CTX_data_scene(C);
831   ViewLayer *view_layer = CTX_data_view_layer(C);
832
833   if (!ED_scene_view_layer_delete(bmain, scene, view_layer, NULL)) {
834     return OPERATOR_CANCELLED;
835   }
836
837   WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
838
839   return OPERATOR_FINISHED;
840 }
841
842 void SCENE_OT_view_layer_remove(wmOperatorType *ot)
843 {
844   /* identifiers */
845   ot->name = "Remove View Layer";
846   ot->idname = "SCENE_OT_view_layer_remove";
847   ot->description = "Remove the selected view layer";
848
849   /* api callbacks */
850   ot->exec = view_layer_remove_exec;
851   ot->poll = view_layer_remove_poll;
852
853   /* flags */
854   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
855 }
856
857 /********************** light cache operators *********************/
858 enum {
859   LIGHTCACHE_SUBSET_ALL = 0,
860   LIGHTCACHE_SUBSET_DIRTY,
861   LIGHTCACHE_SUBSET_CUBE,
862 };
863
864 static void light_cache_bake_tag_cache(Scene *scene, wmOperator *op)
865 {
866   if (scene->eevee.light_cache != NULL) {
867     int subset = RNA_enum_get(op->ptr, "subset");
868     switch (subset) {
869       case LIGHTCACHE_SUBSET_ALL:
870         scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_GRID | LIGHTCACHE_UPDATE_CUBE;
871         break;
872       case LIGHTCACHE_SUBSET_CUBE:
873         scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_CUBE;
874         break;
875       case LIGHTCACHE_SUBSET_DIRTY:
876         /* Leave tag untouched. */
877         break;
878     }
879   }
880 }
881
882 /* catch esc */
883 static int light_cache_bake_modal(bContext *C, wmOperator *op, const wmEvent *event)
884 {
885   Scene *scene = (Scene *)op->customdata;
886
887   /* no running blender, remove handler and pass through */
888   if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) {
889     return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
890   }
891
892   /* running render */
893   switch (event->type) {
894     case ESCKEY:
895       return OPERATOR_RUNNING_MODAL;
896   }
897   return OPERATOR_PASS_THROUGH;
898 }
899
900 static void light_cache_bake_cancel(bContext *C, wmOperator *op)
901 {
902   wmWindowManager *wm = CTX_wm_manager(C);
903   Scene *scene = (Scene *)op->customdata;
904
905   /* kill on cancel, because job is using op->reports */
906   WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER);
907 }
908
909 /* executes blocking render */
910 static int light_cache_bake_exec(bContext *C, wmOperator *op)
911 {
912   ViewLayer *view_layer = CTX_data_view_layer(C);
913   Main *bmain = CTX_data_main(C);
914   Scene *scene = CTX_data_scene(C);
915
916   G.is_break = false;
917
918   /* TODO abort if selected engine is not eevee. */
919   void *rj = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, false, scene->r.cfra);
920
921   light_cache_bake_tag_cache(scene, op);
922
923   short stop = 0, do_update;
924   float progress; /* Not actually used. */
925   EEVEE_lightbake_job(rj, &stop, &do_update, &progress);
926   EEVEE_lightbake_job_data_free(rj);
927
928   // no redraw needed, we leave state as we entered it
929   ED_update_for_newframe(bmain, CTX_data_depsgraph_pointer(C));
930
931   WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
932
933   return OPERATOR_FINISHED;
934 }
935
936 static int light_cache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
937 {
938   wmWindowManager *wm = CTX_wm_manager(C);
939   wmWindow *win = CTX_wm_window(C);
940   ViewLayer *view_layer = CTX_data_view_layer(C);
941   Main *bmain = CTX_data_main(C);
942   Scene *scene = CTX_data_scene(C);
943   int delay = RNA_int_get(op->ptr, "delay");
944
945   wmJob *wm_job = EEVEE_lightbake_job_create(
946       wm, win, bmain, view_layer, scene, delay, scene->r.cfra);
947
948   if (!wm_job) {
949     return OPERATOR_CANCELLED;
950   }
951
952   /* add modal handler for ESC */
953   WM_event_add_modal_handler(C, op);
954
955   light_cache_bake_tag_cache(scene, op);
956
957   /* store actual owner of job, so modal operator could check for it,
958    * the reason of this is that active scene could change when rendering
959    * several layers from compositor [#31800]
960    */
961   op->customdata = scene;
962
963   WM_jobs_start(wm, wm_job);
964
965   WM_cursor_wait(0);
966
967   return OPERATOR_RUNNING_MODAL;
968 }
969
970 void SCENE_OT_light_cache_bake(wmOperatorType *ot)
971 {
972   static const EnumPropertyItem light_cache_subset_items[] = {
973       {LIGHTCACHE_SUBSET_ALL,
974        "ALL",
975        0,
976        "All LightProbes",
977        "Bake both irradiance grids and reflection cubemaps"},
978       {LIGHTCACHE_SUBSET_DIRTY,
979        "DIRTY",
980        0,
981        "Dirty Only",
982        "Only bake lightprobes that are marked as dirty"},
983       {LIGHTCACHE_SUBSET_CUBE,
984        "CUBEMAPS",
985        0,
986        "Cubemaps Only",
987        "Try to only bake reflection cubemaps if irradiance grids are up to date"},
988       {0, NULL, 0, NULL, NULL},
989   };
990
991   /* identifiers */
992   ot->name = "Bake Light Cache";
993   ot->idname = "SCENE_OT_light_cache_bake";
994   ot->description = "Bake the active view layer lighting";
995
996   /* api callbacks */
997   ot->invoke = light_cache_bake_invoke;
998   ot->modal = light_cache_bake_modal;
999   ot->cancel = light_cache_bake_cancel;
1000   ot->exec = light_cache_bake_exec;
1001
1002   ot->prop = RNA_def_int(ot->srna,
1003                          "delay",
1004                          0,
1005                          0,
1006                          2000,
1007                          "Delay",
1008                          "Delay in millisecond before baking starts",
1009                          0,
1010                          2000);
1011   RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
1012
1013   ot->prop = RNA_def_enum(
1014       ot->srna, "subset", light_cache_subset_items, 0, "Subset", "Subset of probes to update");
1015   RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
1016 }
1017
1018 static bool light_cache_free_poll(bContext *C)
1019 {
1020   Scene *scene = CTX_data_scene(C);
1021
1022   return scene->eevee.light_cache;
1023 }
1024
1025 static int light_cache_free_exec(bContext *C, wmOperator *UNUSED(op))
1026 {
1027   Scene *scene = CTX_data_scene(C);
1028
1029   /* kill potential bake job first (see T57011) */
1030   wmWindowManager *wm = CTX_wm_manager(C);
1031   WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_LIGHT_BAKE);
1032
1033   if (!scene->eevee.light_cache) {
1034     return OPERATOR_CANCELLED;
1035   }
1036
1037   EEVEE_lightcache_free(scene->eevee.light_cache);
1038   scene->eevee.light_cache = NULL;
1039
1040   EEVEE_lightcache_info_update(&scene->eevee);
1041
1042   DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
1043
1044   WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1045
1046   return OPERATOR_FINISHED;
1047 }
1048
1049 void SCENE_OT_light_cache_free(wmOperatorType *ot)
1050 {
1051   /* identifiers */
1052   ot->name = "Delete Light Cache";
1053   ot->idname = "SCENE_OT_light_cache_free";
1054   ot->description = "Delete cached indirect lighting";
1055
1056   /* api callbacks */
1057   ot->exec = light_cache_free_exec;
1058   ot->poll = light_cache_free_poll;
1059 }
1060
1061 /********************** render view operators *********************/
1062
1063 static bool render_view_remove_poll(bContext *C)
1064 {
1065   Scene *scene = CTX_data_scene(C);
1066
1067   /* don't allow user to remove "left" and "right" views */
1068   return scene->r.actview > 1;
1069 }
1070
1071 static int render_view_add_exec(bContext *C, wmOperator *UNUSED(op))
1072 {
1073   Scene *scene = CTX_data_scene(C);
1074
1075   BKE_scene_add_render_view(scene, NULL);
1076   scene->r.actview = BLI_listbase_count(&scene->r.views) - 1;
1077
1078   WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1079
1080   return OPERATOR_FINISHED;
1081 }
1082
1083 void SCENE_OT_render_view_add(wmOperatorType *ot)
1084 {
1085   /* identifiers */
1086   ot->name = "Add Render View";
1087   ot->idname = "SCENE_OT_render_view_add";
1088   ot->description = "Add a render view";
1089
1090   /* api callbacks */
1091   ot->exec = render_view_add_exec;
1092
1093   /* flags */
1094   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1095 }
1096
1097 static int render_view_remove_exec(bContext *C, wmOperator *UNUSED(op))
1098 {
1099   Scene *scene = CTX_data_scene(C);
1100   SceneRenderView *rv = BLI_findlink(&scene->r.views, scene->r.actview);
1101
1102   if (!BKE_scene_remove_render_view(scene, rv)) {
1103     return OPERATOR_CANCELLED;
1104   }
1105
1106   WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1107
1108   return OPERATOR_FINISHED;
1109 }
1110
1111 void SCENE_OT_render_view_remove(wmOperatorType *ot)
1112 {
1113   /* identifiers */
1114   ot->name = "Remove Render View";
1115   ot->idname = "SCENE_OT_render_view_remove";
1116   ot->description = "Remove the selected render view";
1117
1118   /* api callbacks */
1119   ot->exec = render_view_remove_exec;
1120   ot->poll = render_view_remove_poll;
1121
1122   /* flags */
1123   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1124 }
1125
1126 #ifdef WITH_FREESTYLE
1127
1128 static bool freestyle_linestyle_check_report(FreestyleLineSet *lineset, ReportList *reports)
1129 {
1130   if (!lineset) {
1131     BKE_report(reports,
1132                RPT_ERROR,
1133                "No active lineset and associated line style to manipulate the modifier");
1134     return false;
1135   }
1136   if (!lineset->linestyle) {
1137     BKE_report(reports,
1138                RPT_ERROR,
1139                "The active lineset does not have a line style (indicating data corruption)");
1140     return false;
1141   }
1142
1143   return true;
1144 }
1145
1146 static bool freestyle_active_module_poll(bContext *C)
1147 {
1148   PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
1149   FreestyleModuleConfig *module = ptr.data;
1150
1151   return module != NULL;
1152 }
1153
1154 static int freestyle_module_add_exec(bContext *C, wmOperator *UNUSED(op))
1155 {
1156   Scene *scene = CTX_data_scene(C);
1157   ViewLayer *view_layer = CTX_data_view_layer(C);
1158
1159   BKE_freestyle_module_add(&view_layer->freestyle_config);
1160
1161   WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1162
1163   return OPERATOR_FINISHED;
1164 }
1165
1166 void SCENE_OT_freestyle_module_add(wmOperatorType *ot)
1167 {
1168   /* identifiers */
1169   ot->name = "Add Freestyle Module";
1170   ot->idname = "SCENE_OT_freestyle_module_add";
1171   ot->description = "Add a style module into the list of modules";
1172
1173   /* api callbacks */
1174   ot->exec = freestyle_module_add_exec;
1175
1176   /* flags */
1177   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1178 }
1179
1180 static int freestyle_module_remove_exec(bContext *C, wmOperator *UNUSED(op))
1181 {
1182   Scene *scene = CTX_data_scene(C);
1183   ViewLayer *view_layer = CTX_data_view_layer(C);
1184   PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
1185   FreestyleModuleConfig *module = ptr.data;
1186
1187   BKE_freestyle_module_delete(&view_layer->freestyle_config, module);
1188
1189   DEG_id_tag_update(&scene->id, 0);
1190   WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1191
1192   return OPERATOR_FINISHED;
1193 }
1194
1195 void SCENE_OT_freestyle_module_remove(wmOperatorType *ot)
1196 {
1197   /* identifiers */
1198   ot->name = "Remove Freestyle Module";
1199   ot->idname = "SCENE_OT_freestyle_module_remove";
1200   ot->description = "Remove the style module from the stack";
1201
1202   /* api callbacks */
1203   ot->poll = freestyle_active_module_poll;
1204   ot->exec = freestyle_module_remove_exec;
1205
1206   /* flags */
1207   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1208 }
1209
1210 static int freestyle_module_move_exec(bContext *C, wmOperator *op)
1211 {
1212   Scene *scene = CTX_data_scene(C);
1213   ViewLayer *view_layer = CTX_data_view_layer(C);
1214   PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
1215   FreestyleModuleConfig *module = ptr.data;
1216   int dir = RNA_enum_get(op->ptr, "direction");
1217
1218   if (BKE_freestyle_module_move(&view_layer->freestyle_config, module, dir)) {
1219     DEG_id_tag_update(&scene->id, 0);
1220     WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1221   }
1222
1223   return OPERATOR_FINISHED;
1224 }
1225
1226 void SCENE_OT_freestyle_module_move(wmOperatorType *ot)
1227 {
1228   static const EnumPropertyItem direction_items[] = {
1229       {-1, "UP", 0, "Up", ""},
1230       {1, "DOWN", 0, "Down", ""},
1231       {0, NULL, 0, NULL, NULL},
1232   };
1233
1234   /* identifiers */
1235   ot->name = "Move Freestyle Module";
1236   ot->idname = "SCENE_OT_freestyle_module_move";
1237   ot->description = "Change the position of the style module within in the list of style modules";
1238
1239   /* api callbacks */
1240   ot->poll = freestyle_active_module_poll;
1241   ot->exec = freestyle_module_move_exec;
1242
1243   /* flags */
1244   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1245
1246   /* props */
1247   RNA_def_enum(ot->srna,
1248                "direction",
1249                direction_items,
1250                0,
1251                "Direction",
1252                "Direction to move the chosen style module towards");
1253 }
1254
1255 static int freestyle_lineset_add_exec(bContext *C, wmOperator *UNUSED(op))
1256 {
1257   Main *bmain = CTX_data_main(C);
1258   Scene *scene = CTX_data_scene(C);
1259   ViewLayer *view_layer = CTX_data_view_layer(C);
1260
1261   BKE_freestyle_lineset_add(bmain, &view_layer->freestyle_config, NULL);
1262
1263   DEG_id_tag_update(&scene->id, 0);
1264   WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1265
1266   return OPERATOR_FINISHED;
1267 }
1268
1269 void SCENE_OT_freestyle_lineset_add(wmOperatorType *ot)
1270 {
1271   /* identifiers */
1272   ot->name = "Add Line Set";
1273   ot->idname = "SCENE_OT_freestyle_lineset_add";
1274   ot->description = "Add a line set into the list of line sets";
1275
1276   /* api callbacks */
1277   ot->exec = freestyle_lineset_add_exec;
1278
1279   /* flags */
1280   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1281 }
1282
1283 static bool freestyle_active_lineset_poll(bContext *C)
1284 {
1285   ViewLayer *view_layer = CTX_data_view_layer(C);
1286
1287   if (!view_layer) {
1288     return false;
1289   }
1290
1291   return BKE_freestyle_lineset_get_active(&view_layer->freestyle_config) != NULL;
1292 }
1293
1294 static int freestyle_lineset_copy_exec(bContext *C, wmOperator *UNUSED(op))
1295 {
1296   ViewLayer *view_layer = CTX_data_view_layer(C);
1297
1298   FRS_copy_active_lineset(&view_layer->freestyle_config);
1299
1300   return OPERATOR_FINISHED;
1301 }
1302
1303 void SCENE_OT_freestyle_lineset_copy(wmOperatorType *ot)
1304 {
1305   /* identifiers */
1306   ot->name = "Copy Line Set";
1307   ot->idname = "SCENE_OT_freestyle_lineset_copy";
1308   ot->description = "Copy the active line set to a buffer";
1309
1310   /* api callbacks */
1311   ot->exec = freestyle_lineset_copy_exec;
1312   ot->poll = freestyle_active_lineset_poll;
1313
1314   /* flags */
1315   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1316 }
1317
1318 static int freestyle_lineset_paste_exec(bContext *C, wmOperator *UNUSED(op))
1319 {
1320   Scene *scene = CTX_data_scene(C);
1321   ViewLayer *view_layer = CTX_data_view_layer(C);
1322
1323   FRS_paste_active_lineset(&view_layer->freestyle_config);
1324
1325   DEG_id_tag_update(&scene->id, 0);
1326   WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1327
1328   return OPERATOR_FINISHED;
1329 }
1330
1331 void SCENE_OT_freestyle_lineset_paste(wmOperatorType *ot)
1332 {
1333   /* identifiers */
1334   ot->name = "Paste Line Set";
1335   ot->idname = "SCENE_OT_freestyle_lineset_paste";
1336   ot->description = "Paste the buffer content to the active line set";
1337
1338   /* api callbacks */
1339   ot->exec = freestyle_lineset_paste_exec;
1340   ot->poll = freestyle_active_lineset_poll;
1341
1342   /* flags */
1343   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1344 }
1345
1346 static int freestyle_lineset_remove_exec(bContext *C, wmOperator *UNUSED(op))
1347 {
1348   Scene *scene = CTX_data_scene(C);
1349   ViewLayer *view_layer = CTX_data_view_layer(C);
1350
1351   FRS_delete_active_lineset(&view_layer->freestyle_config);
1352
1353   DEG_id_tag_update(&scene->id, 0);
1354   WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1355
1356   return OPERATOR_FINISHED;
1357 }
1358
1359 void SCENE_OT_freestyle_lineset_remove(wmOperatorType *ot)
1360 {
1361   /* identifiers */
1362   ot->name = "Remove Line Set";
1363   ot->idname = "SCENE_OT_freestyle_lineset_remove";
1364   ot->description = "Remove the active line set from the list of line sets";
1365
1366   /* api callbacks */
1367   ot->exec = freestyle_lineset_remove_exec;
1368   ot->poll = freestyle_active_lineset_poll;
1369
1370   /* flags */
1371   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1372 }
1373
1374 static int freestyle_lineset_move_exec(bContext *C, wmOperator *op)
1375 {
1376   Scene *scene = CTX_data_scene(C);
1377   ViewLayer *view_layer = CTX_data_view_layer(C);
1378   int dir = RNA_enum_get(op->ptr, "direction");
1379
1380   if (FRS_move_active_lineset(&view_layer->freestyle_config, dir)) {
1381     DEG_id_tag_update(&scene->id, 0);
1382     WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1383   }
1384
1385   return OPERATOR_FINISHED;
1386 }
1387
1388 void SCENE_OT_freestyle_lineset_move(wmOperatorType *ot)
1389 {
1390   static const EnumPropertyItem direction_items[] = {
1391       {-1, "UP", 0, "Up", ""},
1392       {1, "DOWN", 0, "Down", ""},
1393       {0, NULL, 0, NULL, NULL},
1394   };
1395
1396   /* identifiers */
1397   ot->name = "Move Line Set";
1398   ot->idname = "SCENE_OT_freestyle_lineset_move";
1399   ot->description = "Change the position of the active line set within the list of line sets";
1400
1401   /* api callbacks */
1402   ot->exec = freestyle_lineset_move_exec;
1403   ot->poll = freestyle_active_lineset_poll;
1404
1405   /* flags */
1406   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1407
1408   /* props */
1409   RNA_def_enum(ot->srna,
1410                "direction",
1411                direction_items,
1412                0,
1413                "Direction",
1414                "Direction to move the active line set towards");
1415 }
1416
1417 static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op)
1418 {
1419   Main *bmain = CTX_data_main(C);
1420   ViewLayer *view_layer = CTX_data_view_layer(C);
1421   FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1422
1423   if (!lineset) {
1424     BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to");
1425     return OPERATOR_CANCELLED;
1426   }
1427   if (lineset->linestyle) {
1428     id_us_min(&lineset->linestyle->id);
1429     lineset->linestyle = BKE_linestyle_copy(bmain, lineset->linestyle);
1430   }
1431   else {
1432     lineset->linestyle = BKE_linestyle_new(bmain, "LineStyle");
1433   }
1434   DEG_id_tag_update(&lineset->linestyle->id, 0);
1435   WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1436
1437   return OPERATOR_FINISHED;
1438 }
1439
1440 void SCENE_OT_freestyle_linestyle_new(wmOperatorType *ot)
1441 {
1442   /* identifiers */
1443   ot->name = "New Line Style";
1444   ot->idname = "SCENE_OT_freestyle_linestyle_new";
1445   ot->description = "Create a new line style, reusable by multiple line sets";
1446
1447   /* api callbacks */
1448   ot->exec = freestyle_linestyle_new_exec;
1449   ot->poll = freestyle_active_lineset_poll;
1450
1451   /* flags */
1452   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1453 }
1454
1455 static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op)
1456 {
1457   ViewLayer *view_layer = CTX_data_view_layer(C);
1458   FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1459   int type = RNA_enum_get(op->ptr, "type");
1460
1461   if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1462     return OPERATOR_CANCELLED;
1463   }
1464
1465   if (BKE_linestyle_color_modifier_add(lineset->linestyle, NULL, type) == NULL) {
1466     BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type");
1467     return OPERATOR_CANCELLED;
1468   }
1469   DEG_id_tag_update(&lineset->linestyle->id, 0);
1470   WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1471
1472   return OPERATOR_FINISHED;
1473 }
1474
1475 void SCENE_OT_freestyle_color_modifier_add(wmOperatorType *ot)
1476 {
1477   /* identifiers */
1478   ot->name = "Add Line Color Modifier";
1479   ot->idname = "SCENE_OT_freestyle_color_modifier_add";
1480   ot->description =
1481       "Add a line color modifier to the line style associated with the active lineset";
1482
1483   /* api callbacks */
1484   ot->invoke = WM_menu_invoke;
1485   ot->exec = freestyle_color_modifier_add_exec;
1486   ot->poll = freestyle_active_lineset_poll;
1487
1488   /* flags */
1489   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1490
1491   /* properties */
1492   ot->prop = RNA_def_enum(
1493       ot->srna, "type", rna_enum_linestyle_color_modifier_type_items, 0, "Type", "");
1494 }
1495
1496 static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op)
1497 {
1498   ViewLayer *view_layer = CTX_data_view_layer(C);
1499   FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1500   int type = RNA_enum_get(op->ptr, "type");
1501
1502   if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1503     return OPERATOR_CANCELLED;
1504   }
1505
1506   if (BKE_linestyle_alpha_modifier_add(lineset->linestyle, NULL, type) == NULL) {
1507     BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type");
1508     return OPERATOR_CANCELLED;
1509   }
1510   DEG_id_tag_update(&lineset->linestyle->id, 0);
1511   WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1512
1513   return OPERATOR_FINISHED;
1514 }
1515
1516 void SCENE_OT_freestyle_alpha_modifier_add(wmOperatorType *ot)
1517 {
1518   /* identifiers */
1519   ot->name = "Add Alpha Transparency Modifier";
1520   ot->idname = "SCENE_OT_freestyle_alpha_modifier_add";
1521   ot->description =
1522       "Add an alpha transparency modifier to the line style associated with the active lineset";
1523
1524   /* api callbacks */
1525   ot->invoke = WM_menu_invoke;
1526   ot->exec = freestyle_alpha_modifier_add_exec;
1527   ot->poll = freestyle_active_lineset_poll;
1528
1529   /* flags */
1530   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1531
1532   /* properties */
1533   ot->prop = RNA_def_enum(
1534       ot->srna, "type", rna_enum_linestyle_alpha_modifier_type_items, 0, "Type", "");
1535 }
1536
1537 static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op)
1538 {
1539   ViewLayer *view_layer = CTX_data_view_layer(C);
1540   FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1541   int type = RNA_enum_get(op->ptr, "type");
1542
1543   if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1544     return OPERATOR_CANCELLED;
1545   }
1546
1547   if (BKE_linestyle_thickness_modifier_add(lineset->linestyle, NULL, type) == NULL) {
1548     BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type");
1549     return OPERATOR_CANCELLED;
1550   }
1551   DEG_id_tag_update(&lineset->linestyle->id, 0);
1552   WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1553
1554   return OPERATOR_FINISHED;
1555 }
1556
1557 void SCENE_OT_freestyle_thickness_modifier_add(wmOperatorType *ot)
1558 {
1559   /* identifiers */
1560   ot->name = "Add Line Thickness Modifier";
1561   ot->idname = "SCENE_OT_freestyle_thickness_modifier_add";
1562   ot->description =
1563       "Add a line thickness modifier to the line style associated with the active lineset";
1564
1565   /* api callbacks */
1566   ot->invoke = WM_menu_invoke;
1567   ot->exec = freestyle_thickness_modifier_add_exec;
1568   ot->poll = freestyle_active_lineset_poll;
1569
1570   /* flags */
1571   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1572
1573   /* properties */
1574   ot->prop = RNA_def_enum(
1575       ot->srna, "type", rna_enum_linestyle_thickness_modifier_type_items, 0, "Type", "");
1576 }
1577
1578 static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op)
1579 {
1580   ViewLayer *view_layer = CTX_data_view_layer(C);
1581   FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1582   int type = RNA_enum_get(op->ptr, "type");
1583
1584   if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1585     return OPERATOR_CANCELLED;
1586   }
1587
1588   if (BKE_linestyle_geometry_modifier_add(lineset->linestyle, NULL, type) == NULL) {
1589     BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type");
1590     return OPERATOR_CANCELLED;
1591   }
1592   DEG_id_tag_update(&lineset->linestyle->id, 0);
1593   WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1594
1595   return OPERATOR_FINISHED;
1596 }
1597
1598 void SCENE_OT_freestyle_geometry_modifier_add(wmOperatorType *ot)
1599 {
1600   /* identifiers */
1601   ot->name = "Add Stroke Geometry Modifier";
1602   ot->idname = "SCENE_OT_freestyle_geometry_modifier_add";
1603   ot->description =
1604       "Add a stroke geometry modifier to the line style associated with the active lineset";
1605
1606   /* api callbacks */
1607   ot->invoke = WM_menu_invoke;
1608   ot->exec = freestyle_geometry_modifier_add_exec;
1609   ot->poll = freestyle_active_lineset_poll;
1610
1611   /* flags */
1612   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1613
1614   /* properties */
1615   ot->prop = RNA_def_enum(
1616       ot->srna, "type", rna_enum_linestyle_geometry_modifier_type_items, 0, "Type", "");
1617 }
1618
1619 static int freestyle_get_modifier_type(PointerRNA *ptr)
1620 {
1621   if (RNA_struct_is_a(ptr->type, &RNA_LineStyleColorModifier)) {
1622     return LS_MODIFIER_TYPE_COLOR;
1623   }
1624   else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleAlphaModifier)) {
1625     return LS_MODIFIER_TYPE_ALPHA;
1626   }
1627   else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleThicknessModifier)) {
1628     return LS_MODIFIER_TYPE_THICKNESS;
1629   }
1630   else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleGeometryModifier)) {
1631     return LS_MODIFIER_TYPE_GEOMETRY;
1632   }
1633   return -1;
1634 }
1635
1636 static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op)
1637 {
1638   ViewLayer *view_layer = CTX_data_view_layer(C);
1639   FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1640   PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
1641   LineStyleModifier *modifier = ptr.data;
1642
1643   if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1644     return OPERATOR_CANCELLED;
1645   }
1646
1647   switch (freestyle_get_modifier_type(&ptr)) {
1648     case LS_MODIFIER_TYPE_COLOR:
1649       BKE_linestyle_color_modifier_remove(lineset->linestyle, modifier);
1650       break;
1651     case LS_MODIFIER_TYPE_ALPHA:
1652       BKE_linestyle_alpha_modifier_remove(lineset->linestyle, modifier);
1653       break;
1654     case LS_MODIFIER_TYPE_THICKNESS:
1655       BKE_linestyle_thickness_modifier_remove(lineset->linestyle, modifier);
1656       break;
1657     case LS_MODIFIER_TYPE_GEOMETRY:
1658       BKE_linestyle_geometry_modifier_remove(lineset->linestyle, modifier);
1659       break;
1660     default:
1661       BKE_report(
1662           op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
1663       return OPERATOR_CANCELLED;
1664   }
1665   DEG_id_tag_update(&lineset->linestyle->id, 0);
1666   WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1667
1668   return OPERATOR_FINISHED;
1669 }
1670
1671 void SCENE_OT_freestyle_modifier_remove(wmOperatorType *ot)
1672 {
1673   /* identifiers */
1674   ot->name = "Remove Modifier";
1675   ot->idname = "SCENE_OT_freestyle_modifier_remove";
1676   ot->description = "Remove the modifier from the list of modifiers";
1677
1678   /* api callbacks */
1679   ot->exec = freestyle_modifier_remove_exec;
1680   ot->poll = freestyle_active_lineset_poll;
1681
1682   /* flags */
1683   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1684 }
1685
1686 static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op)
1687 {
1688   ViewLayer *view_layer = CTX_data_view_layer(C);
1689   FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1690   PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
1691   LineStyleModifier *modifier = ptr.data;
1692
1693   if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1694     return OPERATOR_CANCELLED;
1695   }
1696
1697   switch (freestyle_get_modifier_type(&ptr)) {
1698     case LS_MODIFIER_TYPE_COLOR:
1699       BKE_linestyle_color_modifier_copy(lineset->linestyle, modifier, 0);
1700       break;
1701     case LS_MODIFIER_TYPE_ALPHA:
1702       BKE_linestyle_alpha_modifier_copy(lineset->linestyle, modifier, 0);
1703       break;
1704     case LS_MODIFIER_TYPE_THICKNESS:
1705       BKE_linestyle_thickness_modifier_copy(lineset->linestyle, modifier, 0);
1706       break;
1707     case LS_MODIFIER_TYPE_GEOMETRY:
1708       BKE_linestyle_geometry_modifier_copy(lineset->linestyle, modifier, 0);
1709       break;
1710     default:
1711       BKE_report(
1712           op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
1713       return OPERATOR_CANCELLED;
1714   }
1715   DEG_id_tag_update(&lineset->linestyle->id, 0);
1716   WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1717
1718   return OPERATOR_FINISHED;
1719 }
1720
1721 void SCENE_OT_freestyle_modifier_copy(wmOperatorType *ot)
1722 {
1723   /* identifiers */
1724   ot->name = "Copy Modifier";
1725   ot->idname = "SCENE_OT_freestyle_modifier_copy";
1726   ot->description = "Duplicate the modifier within the list of modifiers";
1727
1728   /* api callbacks */
1729   ot->exec = freestyle_modifier_copy_exec;
1730   ot->poll = freestyle_active_lineset_poll;
1731
1732   /* flags */
1733   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1734 }
1735
1736 static int freestyle_modifier_move_exec(bContext *C, wmOperator *op)
1737 {
1738   ViewLayer *view_layer = CTX_data_view_layer(C);
1739   FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1740   PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
1741   LineStyleModifier *modifier = ptr.data;
1742   int dir = RNA_enum_get(op->ptr, "direction");
1743   bool changed = false;
1744
1745   if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1746     return OPERATOR_CANCELLED;
1747   }
1748
1749   switch (freestyle_get_modifier_type(&ptr)) {
1750     case LS_MODIFIER_TYPE_COLOR:
1751       changed = BKE_linestyle_color_modifier_move(lineset->linestyle, modifier, dir);
1752       break;
1753     case LS_MODIFIER_TYPE_ALPHA:
1754       changed = BKE_linestyle_alpha_modifier_move(lineset->linestyle, modifier, dir);
1755       break;
1756     case LS_MODIFIER_TYPE_THICKNESS:
1757       changed = BKE_linestyle_thickness_modifier_move(lineset->linestyle, modifier, dir);
1758       break;
1759     case LS_MODIFIER_TYPE_GEOMETRY:
1760       changed = BKE_linestyle_geometry_modifier_move(lineset->linestyle, modifier, dir);
1761       break;
1762     default:
1763       BKE_report(
1764           op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
1765       return OPERATOR_CANCELLED;
1766   }
1767
1768   if (changed) {
1769     DEG_id_tag_update(&lineset->linestyle->id, 0);
1770     WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1771   }
1772
1773   return OPERATOR_FINISHED;
1774 }
1775
1776 void SCENE_OT_freestyle_modifier_move(wmOperatorType *ot)
1777 {
1778   static const EnumPropertyItem direction_items[] = {
1779       {-1, "UP", 0, "Up", ""},
1780       {1, "DOWN", 0, "Down", ""},
1781       {0, NULL, 0, NULL, NULL},
1782   };
1783
1784   /* identifiers */
1785   ot->name = "Move Modifier";
1786   ot->idname = "SCENE_OT_freestyle_modifier_move";
1787   ot->description = "Move the modifier within the list of modifiers";
1788
1789   /* api callbacks */
1790   ot->exec = freestyle_modifier_move_exec;
1791   ot->poll = freestyle_active_lineset_poll;
1792
1793   /* flags */
1794   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1795
1796   /* props */
1797   RNA_def_enum(ot->srna,
1798                "direction",
1799                direction_items,
1800                0,
1801                "Direction",
1802                "Direction to move the chosen modifier towards");
1803 }
1804
1805 static int freestyle_stroke_material_create_exec(bContext *C, wmOperator *op)
1806 {
1807   Main *bmain = CTX_data_main(C);
1808   ViewLayer *view_layer = CTX_data_view_layer(C);
1809   FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(view_layer);
1810
1811   if (!linestyle) {
1812     BKE_report(op->reports, RPT_ERROR, "No active line style in the current scene");
1813     return OPERATOR_CANCELLED;
1814   }
1815
1816   FRS_create_stroke_material(bmain, linestyle);
1817
1818   return OPERATOR_FINISHED;
1819 }
1820
1821 void SCENE_OT_freestyle_stroke_material_create(wmOperatorType *ot)
1822 {
1823   /* identifiers */
1824   ot->name = "Create Freestyle Stroke Material";
1825   ot->idname = "SCENE_OT_freestyle_stroke_material_create";
1826   ot->description = "Create Freestyle stroke material for testing";
1827
1828   /* api callbacks */
1829   ot->exec = freestyle_stroke_material_create_exec;
1830
1831   /* flags */
1832   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1833 }
1834
1835 #endif /* WITH_FREESTYLE */
1836
1837 static int texture_slot_move_exec(bContext *C, wmOperator *op)
1838 {
1839   ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
1840
1841   if (id) {
1842     MTex **mtex_ar, *mtexswap;
1843     short act;
1844     int type = RNA_enum_get(op->ptr, "type");
1845     struct AnimData *adt = BKE_animdata_from_id(id);
1846
1847     give_active_mtex(id, &mtex_ar, &act);
1848
1849     if (type == -1) { /* Up */
1850       if (act > 0) {
1851         mtexswap = mtex_ar[act];
1852         mtex_ar[act] = mtex_ar[act - 1];
1853         mtex_ar[act - 1] = mtexswap;
1854
1855         BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act - 1, -1, 0);
1856         BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act - 1, 0);
1857         BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0);
1858
1859         set_active_mtex(id, act - 1);
1860       }
1861     }
1862     else { /* Down */
1863       if (act < MAX_MTEX - 1) {
1864         mtexswap = mtex_ar[act];
1865         mtex_ar[act] = mtex_ar[act + 1];
1866         mtex_ar[act + 1] = mtexswap;
1867
1868         BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act + 1, -1, 0);
1869         BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act + 1, 0);
1870         BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0);
1871
1872         set_active_mtex(id, act + 1);
1873       }
1874     }
1875
1876     DEG_id_tag_update(id, 0);
1877     WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C));
1878   }
1879
1880   return OPERATOR_FINISHED;
1881 }
1882
1883 void TEXTURE_OT_slot_move(wmOperatorType *ot)
1884 {
1885   static const EnumPropertyItem slot_move[] = {
1886       {-1, "UP", 0, "Up", ""},
1887       {1, "DOWN", 0, "Down", ""},
1888       {0, NULL, 0, NULL, NULL},
1889   };
1890
1891   /* identifiers */
1892   ot->name = "Move Texture Slot";
1893   ot->idname = "TEXTURE_OT_slot_move";
1894   ot->description = "Move texture slots up and down";
1895
1896   /* api callbacks */
1897   ot->exec = texture_slot_move_exec;
1898
1899   /* flags */
1900   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1901
1902   RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
1903 }
1904
1905 /********************** material operators *********************/
1906
1907 /* material copy/paste */
1908 static int copy_material_exec(bContext *C, wmOperator *UNUSED(op))
1909 {
1910   Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
1911
1912   if (ma == NULL) {
1913     return OPERATOR_CANCELLED;
1914   }
1915
1916   copy_matcopybuf(CTX_data_main(C), ma);
1917
1918   return OPERATOR_FINISHED;
1919 }
1920
1921 void MATERIAL_OT_copy(wmOperatorType *ot)
1922 {
1923   /* identifiers */
1924   ot->name = "Copy Material";
1925   ot->idname = "MATERIAL_OT_copy";
1926   ot->description = "Copy the material settings and nodes";
1927
1928   /* api callbacks */
1929   ot->exec = copy_material_exec;
1930
1931   /* flags */
1932   /* no undo needed since no changes are made to the material */
1933   ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL;
1934 }
1935
1936 static int paste_material_exec(bContext *C, wmOperator *UNUSED(op))
1937 {
1938   Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
1939
1940   if (ma == NULL) {
1941     return OPERATOR_CANCELLED;
1942   }
1943
1944   paste_matcopybuf(CTX_data_main(C), ma);
1945
1946   DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
1947   WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma);
1948
1949   return OPERATOR_FINISHED;
1950 }
1951
1952 void MATERIAL_OT_paste(wmOperatorType *ot)
1953 {
1954   /* identifiers */
1955   ot->name = "Paste Material";
1956   ot->idname = "MATERIAL_OT_paste";
1957   ot->description = "Paste the material settings and nodes";
1958
1959   /* api callbacks */
1960   ot->exec = paste_material_exec;
1961
1962   /* flags */
1963   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1964 }
1965
1966 static short mtexcopied = 0; /* must be reset on file load */
1967 static MTex mtexcopybuf;
1968
1969 void ED_render_clear_mtex_copybuf(void)
1970 { /* use for file reload */
1971   mtexcopied = 0;
1972 }
1973
1974 static void copy_mtex_copybuf(ID *id)
1975 {
1976   MTex **mtex = NULL;
1977
1978   switch (GS(id->name)) {
1979     case ID_PA:
1980       mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
1981       break;
1982     case ID_LS:
1983       mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
1984       break;
1985     default:
1986       break;
1987   }
1988
1989   if (mtex && *mtex) {
1990     memcpy(&mtexcopybuf, *mtex, sizeof(MTex));
1991     mtexcopied = 1;
1992   }
1993   else {
1994     mtexcopied = 0;
1995   }
1996 }
1997
1998 static void paste_mtex_copybuf(ID *id)
1999 {
2000   MTex **mtex = NULL;
2001
2002   if (mtexcopied == 0 || mtexcopybuf.tex == NULL) {
2003     return;
2004   }
2005
2006   switch (GS(id->name)) {
2007     case ID_PA:
2008       mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
2009       break;
2010     case ID_LS:
2011       mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
2012       break;
2013     default:
2014       BLI_assert(!"invalid id type");
2015       return;
2016   }
2017
2018   if (mtex) {
2019     if (*mtex == NULL) {
2020       *mtex = MEM_mallocN(sizeof(MTex), "mtex copy");
2021     }
2022     else if ((*mtex)->tex) {
2023       id_us_min(&(*mtex)->tex->id);
2024     }
2025
2026     memcpy(*mtex, &mtexcopybuf, sizeof(MTex));
2027
2028     id_us_plus((ID *)mtexcopybuf.tex);
2029   }
2030 }
2031
2032 static int copy_mtex_exec(bContext *C, wmOperator *UNUSED(op))
2033 {
2034   ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
2035
2036   if (id == NULL) {
2037     /* copying empty slot */
2038     ED_render_clear_mtex_copybuf();
2039     return OPERATOR_CANCELLED;
2040   }
2041
2042   copy_mtex_copybuf(id);
2043
2044   return OPERATOR_FINISHED;
2045 }
2046
2047 static bool copy_mtex_poll(bContext *C)
2048 {
2049   ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
2050
2051   return (id != NULL);
2052 }
2053
2054 void TEXTURE_OT_slot_copy(wmOperatorType *ot)
2055 {
2056   /* identifiers */
2057   ot->name = "Copy Texture Slot Settings";
2058   ot->idname = "TEXTURE_OT_slot_copy";
2059   ot->description = "Copy the material texture settings and nodes";
2060
2061   /* api callbacks */
2062   ot->exec = copy_mtex_exec;
2063   ot->poll = copy_mtex_poll;
2064
2065   /* flags */
2066   /* no undo needed since no changes are made to the mtex */
2067   ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL;
2068 }
2069
2070 static int paste_mtex_exec(bContext *C, wmOperator *UNUSED(op))
2071 {
2072   ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
2073
2074   if (id == NULL) {
2075     Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
2076     Light *la = CTX_data_pointer_get_type(C, "light", &RNA_Light).data;
2077     World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
2078     ParticleSystem *psys =
2079         CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data;
2080     FreestyleLineStyle *linestyle =
2081         CTX_data_pointer_get_type(C, "line_style", &RNA_FreestyleLineStyle).data;
2082
2083     if (ma) {
2084       id = &ma->id;
2085     }
2086     else if (la) {
2087       id = &la->id;
2088     }
2089     else if (wo) {
2090       id = &wo->id;
2091     }
2092     else if (psys) {
2093       id = &psys->part->id;
2094     }
2095     else if (linestyle) {
2096       id = &linestyle->id;
2097     }
2098
2099     if (id == NULL) {
2100       return OPERATOR_CANCELLED;
2101     }
2102   }
2103
2104   paste_mtex_copybuf(id);
2105
2106   WM_event_add_notifier(C, NC_TEXTURE | ND_SHADING_LINKS, NULL);
2107
2108   return OPERATOR_FINISHED;
2109 }
2110
2111 void TEXTURE_OT_slot_paste(wmOperatorType *ot)
2112 {
2113   /* identifiers */
2114   ot->name = "Paste Texture Slot Settings";
2115   ot->idname = "TEXTURE_OT_slot_paste";
2116   ot->description = "Copy the texture settings and nodes";
2117
2118   /* api callbacks */
2119   ot->exec = paste_mtex_exec;
2120
2121   /* flags */
2122   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
2123 }