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