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