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