remove unused includes
[blender-staging.git] / source / blender / editors / render / render_shading.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * The Original Code is Copyright (C) 2009 Blender Foundation.
20  * All rights reserved.
21  *
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "MEM_guardedalloc.h"
31
32 #include "DNA_curve_types.h"
33 #include "DNA_lamp_types.h"
34 #include "DNA_material_types.h"
35 #include "DNA_node_types.h"
36 #include "DNA_object_types.h"
37 #include "DNA_scene_types.h"
38 #include "DNA_space_types.h"
39 #include "DNA_world_types.h"
40
41 #include "BKE_animsys.h"
42 #include "BKE_context.h"
43 #include "BKE_depsgraph.h"
44 #include "BKE_font.h"
45 #include "BKE_global.h"
46 #include "BKE_icons.h"
47 #include "BKE_image.h"
48 #include "BKE_library.h"
49 #include "BKE_main.h"
50 #include "BKE_material.h"
51 #include "BKE_node.h"
52 #include "BKE_report.h"
53 #include "BKE_scene.h"
54 #include "BKE_texture.h"
55 #include "BKE_world.h"
56
57 #include "IMB_imbuf.h"
58 #include "IMB_imbuf_types.h"
59
60 #include "BLI_blenlib.h"
61 #include "BLI_math.h"
62 #include "BLI_editVert.h"
63 #include "BLI_listbase.h"
64
65 #include "GPU_material.h"
66
67 #include "RNA_access.h"
68
69 #include "WM_api.h"
70 #include "WM_types.h"
71
72 #include "ED_curve.h"
73 #include "ED_mesh.h"
74
75 #include "RNA_define.h"
76
77 #include "UI_interface.h"
78
79 #include "render_intern.h"      // own include
80
81 /***************************** Updates ***********************************
82  * ED_render_id_flush_update gets called from DAG_id_flush_update, to do *
83  * editor level updates when the ID changes. when these ID blocks are in *
84  * the dependency graph, we can get rid of the manual dependency checks  */
85
86 static int mtex_use_tex(MTex **mtex, int tot, Tex *tex)
87 {
88         int a;
89
90         if(!mtex)
91                 return 0;
92
93         for(a=0; a<tot; a++)
94                 if(mtex[a] && mtex[a]->tex == tex)
95                         return 1;
96         
97         return 0;
98 }
99
100 static int nodes_use_tex(bNodeTree *ntree, Tex *tex)
101 {
102         bNode *node;
103
104         for(node=ntree->nodes.first; node; node= node->next) {
105                 if(node->id) {
106                         if(node->id == (ID*)tex) {
107                                 return 1;
108                         }
109                         else if(node->type==NODE_GROUP) {
110                                 if(nodes_use_tex((bNodeTree *)node->id, tex))
111                                         return 1;
112                         }
113                 }
114         }
115
116         return 0;
117 }
118
119 static void material_changed(Main *bmain, Material *ma)
120 {
121         /* icons */
122         BKE_icon_changed(BKE_icon_getid(&ma->id));
123
124         /* glsl */
125         if(ma->gpumaterial.first)
126                 GPU_material_free(ma);
127 }
128
129 static void texture_changed(Main *bmain, Tex *tex)
130 {
131         Material *ma;
132         Lamp *la;
133         World *wo;
134
135         /* icons */
136         BKE_icon_changed(BKE_icon_getid(&tex->id));
137
138         /* find materials */
139         for(ma=bmain->mat.first; ma; ma=ma->id.next) {
140                 if(mtex_use_tex(ma->mtex, MAX_MTEX, tex));
141                 else if(ma->use_nodes && ma->nodetree && nodes_use_tex(ma->nodetree, tex));
142                 else continue;
143
144                 BKE_icon_changed(BKE_icon_getid(&ma->id));
145
146                 if(ma->gpumaterial.first)
147                         GPU_material_free(ma);
148         }
149
150         /* find lamps */
151         for(la=bmain->lamp.first; la; la=la->id.next) {
152                 if(mtex_use_tex(la->mtex, MAX_MTEX, tex));
153                 else continue;
154
155                 BKE_icon_changed(BKE_icon_getid(&la->id));
156         }
157
158         /* find worlds */
159         for(wo=bmain->world.first; wo; wo=wo->id.next) {
160                 if(mtex_use_tex(wo->mtex, MAX_MTEX, tex));
161                 else continue;
162
163                 BKE_icon_changed(BKE_icon_getid(&wo->id));
164         }
165 }
166
167 static void lamp_changed(Main *bmain, Lamp *la)
168 {
169         Object *ob;
170         Material *ma;
171
172         /* icons */
173         BKE_icon_changed(BKE_icon_getid(&la->id));
174
175         /* glsl */
176         for(ob=bmain->object.first; ob; ob=ob->id.next)
177                 if(ob->data == la && ob->gpulamp.first)
178                         GPU_lamp_free(ob);
179
180         for(ma=bmain->mat.first; ma; ma=ma->id.next)
181                 if(ma->gpumaterial.first)
182                         GPU_material_free(ma);
183 }
184
185 static void world_changed(Main *bmain, World *wo)
186 {
187         Material *ma;
188
189         /* icons */
190         BKE_icon_changed(BKE_icon_getid(&wo->id));
191
192         /* glsl */
193         for(ma=bmain->mat.first; ma; ma=ma->id.next)
194                 if(ma->gpumaterial.first)
195                         GPU_material_free(ma);
196 }
197
198 static void image_changed(Main *bmain, Image *ima)
199 {
200         Tex *tex;
201
202         /* icons */
203         BKE_icon_changed(BKE_icon_getid(&ima->id));
204
205         /* textures */
206         for(tex=bmain->tex.first; tex; tex=tex->id.next)
207                 if(tex->ima == ima)
208                         texture_changed(bmain, tex);
209 }
210
211 static void scene_changed(Main *bmain, Scene *sce)
212 {
213         Object *ob;
214         Material *ma;
215
216         /* glsl */
217         for(ob=bmain->object.first; ob; ob=ob->id.next)
218                 if(ob->gpulamp.first)
219                         GPU_lamp_free(ob);
220
221         for(ma=bmain->mat.first; ma; ma=ma->id.next)
222                 if(ma->gpumaterial.first)
223                         GPU_material_free(ma);
224 }
225
226 void ED_render_id_flush_update(Main *bmain, ID *id)
227 {
228         if(!id)
229                 return;
230
231         switch(GS(id->name)) {
232                 case ID_MA:
233                         material_changed(bmain, (Material*)id);
234                         break;
235                 case ID_TE:
236                         texture_changed(bmain, (Tex*)id);
237                         break;
238                 case ID_WO:
239                         world_changed(bmain, (World*)id);
240                         break;
241                 case ID_LA:
242                         lamp_changed(bmain, (Lamp*)id);
243                         break;
244                 case ID_IM:
245                         image_changed(bmain, (Image*)id);
246                         break;
247                 case ID_SCE:
248                         scene_changed(bmain, (Scene*)id);
249                         break;
250                 default:
251                         break;
252         }
253 }
254
255 /********************** material slot operators *********************/
256
257 static int material_slot_add_exec(bContext *C, wmOperator *op)
258 {
259         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
260
261         if(!ob)
262                 return OPERATOR_CANCELLED;
263
264         object_add_material_slot(ob);
265         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
266         
267         return OPERATOR_FINISHED;
268 }
269
270 void OBJECT_OT_material_slot_add(wmOperatorType *ot)
271 {
272         /* identifiers */
273         ot->name= "Add Material Slot";
274         ot->idname= "OBJECT_OT_material_slot_add";
275         ot->description="Add a new material slot or duplicate the selected one";
276         
277         /* api callbacks */
278         ot->exec= material_slot_add_exec;
279
280         /* flags */
281         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
282 }
283
284 static int material_slot_remove_exec(bContext *C, wmOperator *op)
285 {
286         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
287
288         if(!ob)
289                 return OPERATOR_CANCELLED;
290
291         object_remove_material_slot(ob);
292         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
293         
294         return OPERATOR_FINISHED;
295 }
296
297 void OBJECT_OT_material_slot_remove(wmOperatorType *ot)
298 {
299         /* identifiers */
300         ot->name= "Remove Material Slot";
301         ot->idname= "OBJECT_OT_material_slot_remove";
302         ot->description="Remove the selected material slot";
303         
304         /* api callbacks */
305         ot->exec= material_slot_remove_exec;
306
307         /* flags */
308         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
309 }
310
311 static int material_slot_assign_exec(bContext *C, wmOperator *op)
312 {
313         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
314
315         if(!ob)
316                 return OPERATOR_CANCELLED;
317
318         if(ob && ob->actcol>0) {
319                 if(ob->type == OB_MESH) {
320                         EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
321                         EditFace *efa;
322
323                         if(em) {
324                                 for(efa= em->faces.first; efa; efa=efa->next)
325                                         if(efa->f & SELECT)
326                                                 efa->mat_nr= ob->actcol-1;
327                         }
328                 }
329                 else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
330                         Nurb *nu;
331                         ListBase *nurbs= ED_curve_editnurbs((Curve*)ob->data);
332
333                         if(nurbs) {
334                                 for(nu= nurbs->first; nu; nu= nu->next)
335                                         if(isNurbsel(nu))
336                                                 nu->mat_nr= nu->charidx= ob->actcol-1;
337                         }
338                 }
339                 else if(ob->type == OB_FONT) {
340                         EditFont *ef= ((Curve*)ob->data)->editfont;
341                         int i, selstart, selend;
342
343                         if(ef && BKE_font_getselection(ob, &selstart, &selend)) {
344                                 for(i=selstart; i<=selend; i++)
345                                         ef->textbufinfo[i].mat_nr = ob->actcol-1;
346                         }
347                 }
348         }
349
350         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
351         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
352         
353         return OPERATOR_FINISHED;
354 }
355
356 void OBJECT_OT_material_slot_assign(wmOperatorType *ot)
357 {
358         /* identifiers */
359         ot->name= "Assign Material Slot";
360         ot->idname= "OBJECT_OT_material_slot_assign";
361         ot->description="Assign the material in the selected material slot to the selected vertices";
362         
363         /* api callbacks */
364         ot->exec= material_slot_assign_exec;
365
366         /* flags */
367         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
368 }
369
370 static int material_slot_de_select(bContext *C, int select)
371 {
372         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
373
374         if(!ob)
375                 return OPERATOR_CANCELLED;
376
377         if(ob->type == OB_MESH) {
378                 EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
379
380                 if(em) {
381                         if(select)
382                                 EM_select_by_material(em, ob->actcol-1);
383                         else
384                                 EM_deselect_by_material(em, ob->actcol-1);
385                 }
386         }
387         else if ELEM(ob->type, OB_CURVE, OB_SURF) {
388                 ListBase *nurbs= ED_curve_editnurbs((Curve*)ob->data);
389                 Nurb *nu;
390                 BPoint *bp;
391                 BezTriple *bezt;
392                 int a;
393
394                 for(nu= nurbs->first; nu; nu=nu->next) {
395                         if(nu->mat_nr==ob->actcol-1) {
396                                 if(nu->bezt) {
397                                         a= nu->pntsu;
398                                         bezt= nu->bezt;
399                                         while(a--) {
400                                                 if(bezt->hide==0) {
401                                                         if(select) {
402                                                                 bezt->f1 |= SELECT;
403                                                                 bezt->f2 |= SELECT;
404                                                                 bezt->f3 |= SELECT;
405                                                         }
406                                                         else {
407                                                                 bezt->f1 &= ~SELECT;
408                                                                 bezt->f2 &= ~SELECT;
409                                                                 bezt->f3 &= ~SELECT;
410                                                         }
411                                                 }
412                                                 bezt++;
413                                         }
414                                 }
415                                 else if(nu->bp) {
416                                         a= nu->pntsu*nu->pntsv;
417                                         bp= nu->bp;
418                                         while(a--) {
419                                                 if(bp->hide==0) {
420                                                         if(select) bp->f1 |= SELECT;
421                                                         else bp->f1 &= ~SELECT;
422                                                 }
423                                                 bp++;
424                                         }
425                                 }
426                         }
427                 }
428         }
429
430         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
431
432         return OPERATOR_FINISHED;
433 }
434
435 static int material_slot_select_exec(bContext *C, wmOperator *op)
436 {
437         return material_slot_de_select(C, 1);
438 }
439
440 void OBJECT_OT_material_slot_select(wmOperatorType *ot)
441 {
442         /* identifiers */
443         ot->name= "Select Material Slot";
444         ot->idname= "OBJECT_OT_material_slot_select";
445         ot->description="Select vertices assigned to the selected material slot";
446         
447         /* api callbacks */
448         ot->exec= material_slot_select_exec;
449
450         /* flags */
451         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
452 }
453
454 static int material_slot_deselect_exec(bContext *C, wmOperator *op)
455 {
456         return material_slot_de_select(C, 0);
457 }
458
459 void OBJECT_OT_material_slot_deselect(wmOperatorType *ot)
460 {
461         /* identifiers */
462         ot->name= "Deselect Material Slot";
463         ot->idname= "OBJECT_OT_material_slot_deselect";
464         ot->description="Deselect vertices assigned to the selected material slot";
465         
466         /* api callbacks */
467         ot->exec= material_slot_deselect_exec;
468
469         /* flags */
470         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
471 }
472
473
474 static int material_slot_copy_exec(bContext *C, wmOperator *op)
475 {
476         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
477         Material ***matar;
478
479         if(!ob || !(matar= give_matarar(ob)))
480                 return OPERATOR_CANCELLED;
481
482         CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) {
483                 if(ob != ob_iter && give_matarar(ob_iter)) {
484                         if (ob->data != ob_iter->data)
485                                 assign_matarar(ob_iter, matar, ob->totcol);
486                         
487                         if(ob_iter->totcol==ob->totcol) {
488                                 ob_iter->actcol= ob->actcol;
489                                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob_iter);
490                         }
491                 }
492         }
493         CTX_DATA_END;
494
495         return OPERATOR_FINISHED;
496 }
497
498
499 void OBJECT_OT_material_slot_copy(wmOperatorType *ot)
500 {
501         /* identifiers */
502         ot->name= "Copy Material to Others";
503         ot->idname= "OBJECT_OT_material_slot_copy";
504         ot->description="Copies materials to other selected objects";
505
506         /* api callbacks */
507         ot->exec= material_slot_copy_exec;
508
509         /* flags */
510         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
511 }
512
513 /********************** new material operator *********************/
514
515 static int new_material_exec(bContext *C, wmOperator *op)
516 {
517         Material *ma= CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
518         PointerRNA ptr, idptr;
519         PropertyRNA *prop;
520
521         /* add or copy material */
522         if(ma)
523                 ma= copy_material(ma);
524         else
525                 ma= add_material("Material");
526
527         /* hook into UI */
528         uiIDContextProperty(C, &ptr, &prop);
529
530         if(prop) {
531                 /* when creating new ID blocks, use is already 1, but RNA
532                  * pointer se also increases user, so this compensates it */
533                 ma->id.us--;
534
535                 RNA_id_pointer_create(&ma->id, &idptr);
536                 RNA_property_pointer_set(&ptr, prop, idptr);
537                 RNA_property_update(C, &ptr, prop);
538         }
539
540         WM_event_add_notifier(C, NC_MATERIAL|NA_ADDED, ma);
541         
542         return OPERATOR_FINISHED;
543 }
544
545 void MATERIAL_OT_new(wmOperatorType *ot)
546 {
547         /* identifiers */
548         ot->name= "New Material";
549         ot->idname= "MATERIAL_OT_new";
550         ot->description="Add a new material";
551         
552         /* api callbacks */
553         ot->exec= new_material_exec;
554
555         /* flags */
556         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
557 }
558
559 /********************** new texture operator *********************/
560
561 static int new_texture_exec(bContext *C, wmOperator *op)
562 {
563         Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
564         PointerRNA ptr, idptr;
565         PropertyRNA *prop;
566
567         /* add or copy texture */
568         if(tex)
569                 tex= copy_texture(tex);
570         else
571                 tex= add_texture("Texture");
572
573         /* hook into UI */
574         uiIDContextProperty(C, &ptr, &prop);
575
576         if(prop) {
577                 /* when creating new ID blocks, use is already 1, but RNA
578                  * pointer se also increases user, so this compensates it */
579                 tex->id.us--;
580
581                 RNA_id_pointer_create(&tex->id, &idptr);
582                 RNA_property_pointer_set(&ptr, prop, idptr);
583                 RNA_property_update(C, &ptr, prop);
584         }
585
586         WM_event_add_notifier(C, NC_TEXTURE|NA_ADDED, tex);
587         
588         return OPERATOR_FINISHED;
589 }
590
591 void TEXTURE_OT_new(wmOperatorType *ot)
592 {
593         /* identifiers */
594         ot->name= "New Texture";
595         ot->idname= "TEXTURE_OT_new";
596         ot->description="Add a new texture";
597         
598         /* api callbacks */
599         ot->exec= new_texture_exec;
600
601         /* flags */
602         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
603 }
604
605 /********************** new world operator *********************/
606
607 static int new_world_exec(bContext *C, wmOperator *op)
608 {
609         World *wo= CTX_data_pointer_get_type(C, "world", &RNA_World).data;
610         PointerRNA ptr, idptr;
611         PropertyRNA *prop;
612
613         /* add or copy world */
614         if(wo)
615                 wo= copy_world(wo);
616         else
617                 wo= add_world("World");
618
619         /* hook into UI */
620         uiIDContextProperty(C, &ptr, &prop);
621
622         if(prop) {
623                 /* when creating new ID blocks, use is already 1, but RNA
624                  * pointer se also increases user, so this compensates it */
625                 wo->id.us--;
626
627                 RNA_id_pointer_create(&wo->id, &idptr);
628                 RNA_property_pointer_set(&ptr, prop, idptr);
629                 RNA_property_update(C, &ptr, prop);
630         }
631
632         WM_event_add_notifier(C, NC_WORLD|NA_ADDED, wo);
633         
634         return OPERATOR_FINISHED;
635 }
636
637 void WORLD_OT_new(wmOperatorType *ot)
638 {
639         /* identifiers */
640         ot->name= "New World";
641         ot->idname= "WORLD_OT_new";
642         ot->description= "Add a new world";
643         
644         /* api callbacks */
645         ot->exec= new_world_exec;
646
647         /* flags */
648         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
649 }
650
651 /********************** render layer operators *********************/
652
653 static int render_layer_add_exec(bContext *C, wmOperator *op)
654 {
655         Scene *scene= CTX_data_scene(C);
656
657         scene_add_render_layer(scene);
658         scene->r.actlay= BLI_countlist(&scene->r.layers) - 1;
659
660         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
661         
662         return OPERATOR_FINISHED;
663 }
664
665 void SCENE_OT_render_layer_add(wmOperatorType *ot)
666 {
667         /* identifiers */
668         ot->name= "Add Render Layer";
669         ot->idname= "SCENE_OT_render_layer_add";
670         ot->description="Add a render layer";
671         
672         /* api callbacks */
673         ot->exec= render_layer_add_exec;
674
675         /* flags */
676         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
677 }
678
679 static int render_layer_remove_exec(bContext *C, wmOperator *op)
680 {
681         Scene *scene= CTX_data_scene(C);
682         SceneRenderLayer *rl;
683         int act= scene->r.actlay;
684
685         if(BLI_countlist(&scene->r.layers) <= 1)
686                 return OPERATOR_CANCELLED;
687         
688         rl= BLI_findlink(&scene->r.layers, scene->r.actlay);
689         BLI_remlink(&scene->r.layers, rl);
690         MEM_freeN(rl);
691
692         scene->r.actlay= 0;
693         
694         if(scene->nodetree) {
695                 bNode *node;
696                 for(node= scene->nodetree->nodes.first; node; node= node->next) {
697                         if(node->type==CMP_NODE_R_LAYERS && node->id==NULL) {
698                                 if(node->custom1==act)
699                                         node->custom1= 0;
700                                 else if(node->custom1>act)
701                                         node->custom1--;
702                         }
703                 }
704         }
705
706         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
707         
708         return OPERATOR_FINISHED;
709 }
710
711 void SCENE_OT_render_layer_remove(wmOperatorType *ot)
712 {
713         /* identifiers */
714         ot->name= "Remove Render Layer";
715         ot->idname= "SCENE_OT_render_layer_remove";
716         ot->description="Remove the selected render layer";
717         
718         /* api callbacks */
719         ot->exec= render_layer_remove_exec;
720
721         /* flags */
722         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
723 }
724
725 static int texture_slot_move(bContext *C, wmOperator *op)
726 {
727         ID *id= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
728         Material *ma = (Material *)id;
729
730         if(id) {
731                 MTex **mtex_ar, *mtexswap;
732                 short act;
733                 int type= RNA_enum_get(op->ptr, "type");
734
735                 give_active_mtex(id, &mtex_ar, &act);
736
737                 if(type == -1) { /* Up */
738                         if(act > 0) {
739                                 mtexswap = mtex_ar[act];
740                                 mtex_ar[act] = mtex_ar[act-1];
741                                 mtex_ar[act-1] = mtexswap;
742                                 
743                                 BKE_animdata_fix_paths_rename(id, ma->adt, "texture_slots", NULL, NULL, act-1, -1, 0);
744                                 BKE_animdata_fix_paths_rename(id, ma->adt, "texture_slots", NULL, NULL, act, act-1, 0);
745                                 BKE_animdata_fix_paths_rename(id, ma->adt, "texture_slots", NULL, NULL, -1, act, 0);
746
747                                 if(GS(id->name)==ID_MA) {
748                                         Material *ma= (Material *)id;
749                                         int mtexuse = ma->septex & (1<<act);
750                                         ma->septex &= ~(1<<act);
751                                         ma->septex |= (ma->septex & (1<<(act-1))) << 1;
752                                         ma->septex &= ~(1<<(act-1));
753                                         ma->septex |= mtexuse >> 1;
754                                 }
755                                 
756                                 set_active_mtex(id, act-1);
757                         }
758                 }
759                 else { /* Down */
760                         if(act < MAX_MTEX-1) {
761                                 mtexswap = mtex_ar[act];
762                                 mtex_ar[act] = mtex_ar[act+1];
763                                 mtex_ar[act+1] = mtexswap;
764                                 
765                                 BKE_animdata_fix_paths_rename(id, ma->adt, "texture_slots", NULL, NULL, act+1, -1, 0);
766                                 BKE_animdata_fix_paths_rename(id, ma->adt, "texture_slots", NULL, NULL, act, act+1, 0);
767                                 BKE_animdata_fix_paths_rename(id, ma->adt, "texture_slots", NULL, NULL, -1, act, 0);
768
769                                 if(GS(id->name)==ID_MA) {
770                                         Material *ma= (Material *)id;
771                                         int mtexuse = ma->septex & (1<<act);
772                                         ma->septex &= ~(1<<act);
773                                         ma->septex |= (ma->septex & (1<<(act+1))) >> 1;
774                                         ma->septex &= ~(1<<(act+1));
775                                         ma->septex |= mtexuse << 1;
776                                 }
777                                 
778                                 set_active_mtex(id, act+1);
779                         }
780                 }
781
782                 WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C));
783         }
784
785         return OPERATOR_FINISHED;
786 }
787
788 void TEXTURE_OT_slot_move(wmOperatorType *ot)
789 {
790         static EnumPropertyItem slot_move[] = {
791                 {-1, "UP", 0, "Up", ""},
792                 {1, "DOWN", 0, "Down", ""},
793                 {0, NULL, 0, NULL, NULL}
794         };
795
796         /* identifiers */
797         ot->name= "Move Texture Slot";
798         ot->idname= "TEXTURE_OT_slot_move";
799         ot->description="Move texture slots up and down";
800
801         /* api callbacks */
802         ot->exec= texture_slot_move;
803
804         /* flags */
805         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
806
807         RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
808 }
809
810
811
812 /********************** environment map operators *********************/
813
814 static int save_envmap(wmOperator *op, Scene *scene, EnvMap *env, char *str, int imtype)
815 {
816         ImBuf *ibuf=NULL;
817         int dx;
818         int retval;
819         
820         if(env->cube[1]==NULL) {
821                 BKE_report(op->reports, RPT_ERROR, "There is no generated environment map available to save");
822                 return OPERATOR_CANCELLED;
823         }
824         
825         dx= env->cube[1]->x;
826         
827         if (env->type == ENV_CUBE) {
828                 ibuf = IMB_allocImBuf(3*dx, 2*dx, 24, IB_rectfloat, 0);
829
830                 IMB_rectcpy(ibuf, env->cube[0], 0, 0, 0, 0, dx, dx);
831                 IMB_rectcpy(ibuf, env->cube[1], dx, 0, 0, 0, dx, dx);
832                 IMB_rectcpy(ibuf, env->cube[2], 2*dx, 0, 0, 0, dx, dx);
833                 IMB_rectcpy(ibuf, env->cube[3], 0, dx, 0, 0, dx, dx);
834                 IMB_rectcpy(ibuf, env->cube[4], dx, dx, 0, 0, dx, dx);
835                 IMB_rectcpy(ibuf, env->cube[5], 2*dx, dx, 0, 0, dx, dx);
836         }
837         else if (env->type == ENV_PLANE) {
838                 ibuf = IMB_allocImBuf(dx, dx, 24, IB_rectfloat, 0);
839                 IMB_rectcpy(ibuf, env->cube[1], 0, 0, 0, 0, dx, dx);            
840         }
841         
842         if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
843                 ibuf->profile = IB_PROFILE_LINEAR_RGB;
844         
845         if (BKE_write_ibuf(scene, ibuf, str, imtype, scene->r.subimtype, scene->r.quality)) {
846                 retval = OPERATOR_FINISHED;
847         }
848         else {
849                 BKE_reportf(op->reports, RPT_ERROR, "Error saving environment map to %s.", str);
850                 retval = OPERATOR_CANCELLED;
851         }
852         
853         IMB_freeImBuf(ibuf);
854         ibuf = NULL;
855         
856         return retval;
857 }
858
859 static int envmap_save_exec(bContext *C, wmOperator *op)
860 {
861         Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
862         Scene *scene = CTX_data_scene(C);
863         //int imtype = RNA_enum_get(op->ptr, "file_type");
864         int imtype = scene->r.imtype;
865         char path[FILE_MAX];
866         
867         RNA_string_get(op->ptr, "filepath", path);
868         
869         if(scene->r.scemode & R_EXTENSION)  {
870                 BKE_add_image_extension(path, imtype);
871         }
872         
873         WM_cursor_wait(1);
874         
875         save_envmap(op, scene, tex->env, path, imtype);
876         
877         WM_cursor_wait(0);
878         
879         WM_event_add_notifier(C, NC_TEXTURE, tex);
880         
881         return OPERATOR_FINISHED;
882 }
883
884 static int envmap_save_invoke(bContext *C, wmOperator *op, wmEvent *event)
885 {
886         //Scene *scene= CTX_data_scene(C);
887         
888         if(!RNA_property_is_set(op->ptr, "relative_path"))
889                 RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS);
890         
891         if(RNA_property_is_set(op->ptr, "filepath"))
892                 return envmap_save_exec(C, op);
893
894         //RNA_enum_set(op->ptr, "file_type", scene->r.imtype);
895         
896         RNA_string_set(op->ptr, "filepath", G.sce);
897         WM_event_add_fileselect(C, op);
898         
899         return OPERATOR_RUNNING_MODAL;
900 }
901
902 static int envmap_save_poll(bContext *C)
903 {
904         Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
905
906         if (!tex) 
907                 return 0;
908         if (!tex->env || !tex->env->ok)
909                 return 0;
910         if (tex->env->cube[1]==NULL)
911                 return 0;
912         
913         return 1;
914 }
915
916 void TEXTURE_OT_envmap_save(wmOperatorType *ot)
917 {
918         /* identifiers */
919         ot->name= "Save Environment Map";
920         ot->idname= "TEXTURE_OT_envmap_save";
921         ot->description="Save the current generated Environment map to an image file";
922         
923         /* api callbacks */
924         ot->exec= envmap_save_exec;
925         ot->invoke= envmap_save_invoke;
926         ot->poll= envmap_save_poll;
927         
928         /* flags */
929         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
930         
931         /* properties */
932         //RNA_def_enum(ot->srna, "file_type", image_file_type_items, R_PNG, "File Type", "File type to save image as.");
933         WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE|MOVIEFILE, FILE_SPECIAL, FILE_SAVE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH);
934 }
935
936 static int envmap_clear_exec(bContext *C, wmOperator *op)
937 {
938         Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
939         
940         BKE_free_envmapdata(tex->env);
941         
942         WM_event_add_notifier(C, NC_TEXTURE|NA_EDITED, tex);
943         
944         return OPERATOR_FINISHED;
945 }
946
947 static int envmap_clear_poll(bContext *C)
948 {
949         Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
950         
951         if (!tex) 
952                 return 0;
953         if (!tex->env || !tex->env->ok)
954                 return 0;
955         if (tex->env->cube[1]==NULL)
956                 return 0;
957         
958         return 1;
959 }
960
961 void TEXTURE_OT_envmap_clear(wmOperatorType *ot)
962 {
963         /* identifiers */
964         ot->name= "Clear Environment Map";
965         ot->idname= "TEXTURE_OT_envmap_clear";
966         ot->description="Discard the environment map and free it from memory";
967         
968         /* api callbacks */
969         ot->exec= envmap_clear_exec;
970         ot->poll= envmap_clear_poll;
971         
972         /* flags */
973         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
974 }
975
976 static int envmap_clear_all_exec(bContext *C, wmOperator *op)
977 {
978         Main *bmain = CTX_data_main(C);
979         Tex *tex;
980         
981         for (tex=bmain->tex.first; tex; tex=tex->id.next)
982                 if (tex->env)
983                         BKE_free_envmapdata(tex->env);
984         
985         WM_event_add_notifier(C, NC_TEXTURE|NA_EDITED, tex);
986         
987         return OPERATOR_FINISHED;
988 }
989
990 void TEXTURE_OT_envmap_clear_all(wmOperatorType *ot)
991 {
992         /* identifiers */
993         ot->name= "Clear All Environment Maps";
994         ot->idname= "TEXTURE_OT_envmap_clear_all";
995         ot->description="Discard all environment maps in the .blend file and free them from memory";
996         
997         /* api callbacks */
998         ot->exec= envmap_clear_all_exec;
999         ot->poll= envmap_clear_poll;
1000         
1001         /* flags */
1002         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1003 }
1004
1005 /********************** material operators *********************/
1006
1007 /* material copy/paste */
1008 static int copy_material_exec(bContext *C, wmOperator *op)
1009 {
1010         Material *ma= CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
1011
1012         if(ma==NULL)
1013                 return OPERATOR_CANCELLED;
1014
1015         copy_matcopybuf(ma);
1016
1017         WM_event_add_notifier(C, NC_MATERIAL, ma);
1018
1019         return OPERATOR_FINISHED;
1020 }
1021
1022 void MATERIAL_OT_copy(wmOperatorType *ot)
1023 {
1024         /* identifiers */
1025         ot->name= "Copy Material";
1026         ot->idname= "MATERIAL_OT_copy";
1027         ot->description="Copy the material settings and nodes";
1028
1029         /* api callbacks */
1030         ot->exec= copy_material_exec;
1031
1032         /* flags */
1033         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1034 }
1035
1036 static int paste_material_exec(bContext *C, wmOperator *op)
1037 {
1038         Material *ma= CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
1039
1040         if(ma==NULL)
1041                 return OPERATOR_CANCELLED;
1042
1043         paste_matcopybuf(ma);
1044
1045         WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING_DRAW, ma);
1046
1047         return OPERATOR_FINISHED;
1048 }
1049
1050 void MATERIAL_OT_paste(wmOperatorType *ot)
1051 {
1052         /* identifiers */
1053         ot->name= "Paste Material";
1054         ot->idname= "MATERIAL_OT_paste";
1055         ot->description="Paste the material settings and nodes";
1056
1057         /* api callbacks */
1058         ot->exec= paste_material_exec;
1059
1060         /* flags */
1061         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1062 }
1063
1064
1065 static short mtexcopied=0; /* must be reset on file load */
1066 static MTex mtexcopybuf;
1067
1068 void ED_render_clear_mtex_copybuf(void)
1069 {       /* use for file reload */
1070         mtexcopied= 0;
1071 }
1072
1073 void copy_mtex_copybuf(ID *id)
1074 {
1075         MTex **mtex= NULL;
1076         
1077         switch(GS(id->name)) {
1078                 case ID_MA:
1079                         mtex= &(((Material *)id)->mtex[(int)((Material *)id)->texact]);
1080                         break;
1081                 case ID_LA:
1082                         mtex= &(((Lamp *)id)->mtex[(int)((Lamp *)id)->texact]);
1083                         // la->mtex[(int)la->texact] // TODO
1084                         break;
1085                 case ID_WO:
1086                         mtex= &(((World *)id)->mtex[(int)((World *)id)->texact]);
1087                         // mtex= wrld->mtex[(int)wrld->texact]; // TODO
1088                         break;
1089         }
1090         
1091         if(mtex && *mtex) {
1092                 memcpy(&mtexcopybuf, *mtex, sizeof(MTex));
1093                 mtexcopied= 1;
1094         }
1095         else {
1096                 mtexcopied= 0;
1097         }
1098 }
1099
1100 void paste_mtex_copybuf(ID *id)
1101 {
1102         MTex **mtex= NULL;
1103         
1104         if(mtexcopied == 0 || mtexcopybuf.tex==NULL)
1105                 return;
1106         
1107         switch(GS(id->name)) {
1108                 case ID_MA:
1109                         mtex= &(((Material *)id)->mtex[(int)((Material *)id)->texact]);
1110                         break;
1111                 case ID_LA:
1112                         mtex= &(((Lamp *)id)->mtex[(int)((Lamp *)id)->texact]);
1113                         // la->mtex[(int)la->texact] // TODO
1114                         break;
1115                 case ID_WO:
1116                         mtex= &(((World *)id)->mtex[(int)((World *)id)->texact]);
1117                         // mtex= wrld->mtex[(int)wrld->texact]; // TODO
1118                         break;
1119         }
1120         
1121         if(mtex) {
1122                 if(*mtex==NULL) {
1123                         *mtex= MEM_mallocN(sizeof(MTex), "mtex copy");
1124                 }
1125                 else if((*mtex)->tex) {
1126                         (*mtex)->tex->id.us--;
1127                 }
1128                 
1129                 memcpy(*mtex, &mtexcopybuf, sizeof(MTex));
1130                 
1131                 id_us_plus((ID *)mtexcopybuf.tex);
1132         }
1133 }
1134
1135
1136 static int copy_mtex_exec(bContext *C, wmOperator *op)
1137 {
1138         ID *id= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
1139
1140         if(id==NULL) {
1141                 /* copying empty slot */
1142                 ED_render_clear_mtex_copybuf();
1143                 return OPERATOR_CANCELLED;
1144         }
1145
1146         copy_mtex_copybuf(id);
1147
1148         WM_event_add_notifier(C, NC_TEXTURE, NULL);
1149
1150         return OPERATOR_FINISHED;
1151 }
1152
1153 static int copy_mtex_poll(bContext *C)
1154 {
1155         ID *id= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
1156         
1157         return (id != NULL);
1158 }
1159
1160 void TEXTURE_OT_slot_copy(wmOperatorType *ot)
1161 {
1162         /* identifiers */
1163         ot->name= "Copy Texture Slot Settings";
1164         ot->idname= "TEXTURE_OT_slot_copy";
1165         ot->description="Copy the material texture settings and nodes";
1166
1167         /* api callbacks */
1168         ot->exec= copy_mtex_exec;
1169         ot->poll= copy_mtex_poll;
1170         
1171         /* flags */
1172         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1173 }
1174
1175 static int paste_mtex_exec(bContext *C, wmOperator *op)
1176 {
1177         ID *id= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
1178
1179         if(id==NULL) {
1180                 Material *ma= CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
1181                 Lamp *la= CTX_data_pointer_get_type(C, "lamp", &RNA_Lamp).data;
1182                 World *wo= CTX_data_pointer_get_type(C, "world", &RNA_World).data;
1183                 
1184                 if (ma)
1185                         id = &ma->id;
1186                 else if (la)
1187                         id = &la->id;
1188                 else if (wo)
1189                         id = &wo->id;
1190                 
1191                 if (id==NULL)
1192                         return OPERATOR_CANCELLED;
1193         }
1194
1195         paste_mtex_copybuf(id);
1196
1197         WM_event_add_notifier(C, NC_TEXTURE|ND_SHADING_DRAW, NULL);
1198
1199         return OPERATOR_FINISHED;
1200 }
1201
1202 void TEXTURE_OT_slot_paste(wmOperatorType *ot)
1203 {
1204         /* identifiers */
1205         ot->name= "Paste Texture Slot Settings";
1206         ot->idname= "TEXTURE_OT_slot_paste";
1207         ot->description="Copy the texture settings and nodes";
1208
1209         /* api callbacks */
1210         ot->exec= paste_mtex_exec;
1211
1212         /* flags */
1213         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1214 }