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