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