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