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