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