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