2.5: File browse button in ui layouts now works, e.g. for render
[blender-staging.git] / source / blender / editors / space_buttons / buttons_ops.c
1 /**
2  * $Id:
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2009 Blender Foundation.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "DNA_boid_types.h"
34 #include "DNA_curve_types.h"
35 #include "DNA_group_types.h"
36 #include "DNA_object_types.h"
37 #include "DNA_material_types.h"
38 #include "DNA_node_types.h"
39 #include "DNA_texture_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_screen_types.h"
42 #include "DNA_space_types.h"
43 #include "DNA_world_types.h"
44
45 #include "BKE_context.h"
46 #include "BKE_depsgraph.h"
47 #include "BKE_group.h"
48 #include "BKE_font.h"
49 #include "BKE_library.h"
50 #include "BKE_main.h"
51 #include "BKE_material.h"
52 #include "BKE_node.h"
53 #include "BKE_particle.h"
54 #include "BKE_scene.h"
55 #include "BKE_texture.h"
56 #include "BKE_utildefines.h"
57 #include "BKE_world.h"
58
59 #include "BLI_editVert.h"
60 #include "BLI_listbase.h"
61
62 #include "RNA_access.h"
63 #include "RNA_enum_types.h"
64
65 #include "WM_api.h"
66 #include "WM_types.h"
67
68 #include "ED_curve.h"
69 #include "ED_mesh.h"
70
71 #include "RNA_access.h"
72 #include "RNA_define.h"
73
74 #include "UI_interface.h"
75 #include "UI_resources.h"
76
77 #include "buttons_intern.h"     // own include
78
79
80 /********************** group operators *********************/
81
82 static int group_add_exec(bContext *C, wmOperator *op)
83 {
84         Main *bmain= CTX_data_main(C);
85         Scene *scene= CTX_data_scene(C);
86         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
87         Base *base;
88         Group *group;
89         int value= RNA_enum_get(op->ptr, "group");
90
91         if(!ob)
92                 return OPERATOR_CANCELLED;
93         
94         base= object_in_scene(ob, scene);
95         if(!base)
96                 return OPERATOR_CANCELLED;
97         
98         if(value == -1)
99                 group= add_group( "Group" );
100         else
101                 group= BLI_findlink(&bmain->group, value);
102
103         if(group) {
104                 add_to_group(group, ob);
105                 ob->flag |= OB_FROMGROUP;
106                 base->flag |= OB_FROMGROUP;
107         }
108
109         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
110         
111         return OPERATOR_FINISHED;
112 }
113
114 static EnumPropertyItem group_items[]= {
115         {-1, "ADD_NEW", 0, "Add New Group", ""},
116         {0, NULL, 0, NULL, NULL}};
117
118 static EnumPropertyItem *group_itemf(bContext *C, PointerRNA *ptr, int *free)
119 {       
120         EnumPropertyItem tmp = {0, "", 0, "", ""};
121         EnumPropertyItem *item= NULL;
122         Main *bmain;
123         Group *group;
124         int a, totitem= 0;
125         
126         if(!C) /* needed for docs */
127                 return group_items;
128         
129         RNA_enum_items_add_value(&item, &totitem, group_items, -1);
130
131         bmain= CTX_data_main(C);
132         if(bmain->group.first)
133                 RNA_enum_item_add_separator(&item, &totitem);
134
135         for(a=0, group=bmain->group.first; group; group=group->id.next, a++) {
136                 tmp.value= a;
137                 tmp.identifier= group->id.name+2;
138                 tmp.name= group->id.name+2;
139                 RNA_enum_item_add(&item, &totitem, &tmp);
140         }
141
142         RNA_enum_item_end(&item, &totitem);
143
144         *free= 1;
145
146         return item;
147 }
148
149 void OBJECT_OT_group_add(wmOperatorType *ot)
150 {
151         PropertyRNA *prop;
152
153         /* identifiers */
154         ot->name= "Add Group";
155         ot->idname= "OBJECT_OT_group_add";
156         
157         /* api callbacks */
158         ot->exec= group_add_exec;
159
160         /* flags */
161         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
162
163         /* properties */
164         prop= RNA_def_enum(ot->srna, "group", group_items, -1, "Group", "Group to add object to.");
165         RNA_def_enum_funcs(prop, group_itemf);
166 }
167
168 static int group_remove_exec(bContext *C, wmOperator *op)
169 {
170         Scene *scene= CTX_data_scene(C);
171         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
172         Group *group= CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
173         Base *base;
174
175         if(!ob || !group)
176                 return OPERATOR_CANCELLED;
177
178         base= object_in_scene(ob, scene);
179         if(!base)
180                 return OPERATOR_CANCELLED;
181
182         rem_from_group(group, ob);
183
184         if(find_group(ob, NULL) == NULL) {
185                 ob->flag &= ~OB_FROMGROUP;
186                 base->flag &= ~OB_FROMGROUP;
187         }
188
189         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
190         
191         return OPERATOR_FINISHED;
192 }
193
194 void OBJECT_OT_group_remove(wmOperatorType *ot)
195 {
196         /* identifiers */
197         ot->name= "Remove Group";
198         ot->idname= "OBJECT_OT_group_remove";
199         
200         /* api callbacks */
201         ot->exec= group_remove_exec;
202
203         /* flags */
204         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
205 }
206
207 /********************** material slot operators *********************/
208
209 static int material_slot_add_exec(bContext *C, wmOperator *op)
210 {
211         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
212
213         if(!ob)
214                 return OPERATOR_CANCELLED;
215
216         object_add_material_slot(ob);
217         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
218         
219         return OPERATOR_FINISHED;
220 }
221
222 void OBJECT_OT_material_slot_add(wmOperatorType *ot)
223 {
224         /* identifiers */
225         ot->name= "Add Material Slot";
226         ot->idname= "OBJECT_OT_material_slot_add";
227         
228         /* api callbacks */
229         ot->exec= material_slot_add_exec;
230
231         /* flags */
232         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
233 }
234
235 static int material_slot_remove_exec(bContext *C, wmOperator *op)
236 {
237         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
238
239         if(!ob)
240                 return OPERATOR_CANCELLED;
241
242         object_remove_material_slot(ob);
243         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
244         
245         return OPERATOR_FINISHED;
246 }
247
248 void OBJECT_OT_material_slot_remove(wmOperatorType *ot)
249 {
250         /* identifiers */
251         ot->name= "Remove Material Slot";
252         ot->idname= "OBJECT_OT_material_slot_remove";
253         
254         /* api callbacks */
255         ot->exec= material_slot_remove_exec;
256
257         /* flags */
258         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
259 }
260
261 static int material_slot_assign_exec(bContext *C, wmOperator *op)
262 {
263         Scene *scene= CTX_data_scene(C);
264         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
265
266         if(!ob)
267                 return OPERATOR_CANCELLED;
268
269         if(ob && ob->actcol>0) {
270                 if(ob->type == OB_MESH) {
271                         EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
272                         EditFace *efa;
273
274                         if(em) {
275                                 for(efa= em->faces.first; efa; efa=efa->next)
276                                         if(efa->f & SELECT)
277                                                 efa->mat_nr= ob->actcol-1;
278                         }
279                 }
280                 else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
281                         ListBase *editnurb= ((Curve*)ob->data)->editnurb;
282                         Nurb *nu;
283
284                         if(editnurb) {
285                                 for(nu= editnurb->first; nu; nu= nu->next)
286                                         if(isNurbsel(nu))
287                                                 nu->mat_nr= nu->charidx= ob->actcol-1;
288                         }
289                 }
290                 else if(ob->type == OB_FONT) {
291                         EditFont *ef= ((Curve*)ob->data)->editfont;
292                 int i, selstart, selend;
293
294                         if(ef && BKE_font_getselection(ob, &selstart, &selend)) {
295                                 for(i=selstart; i<=selend; i++)
296                                         ef->textbufinfo[i].mat_nr = ob->actcol-1;
297                         }
298                 }
299         }
300
301     DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
302     WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
303         
304         return OPERATOR_FINISHED;
305 }
306
307 void OBJECT_OT_material_slot_assign(wmOperatorType *ot)
308 {
309         /* identifiers */
310         ot->name= "Assign Material Slot";
311         ot->idname= "OBJECT_OT_material_slot_assign";
312         
313         /* api callbacks */
314         ot->exec= material_slot_assign_exec;
315
316         /* flags */
317         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
318 }
319
320 static int material_slot_de_select(bContext *C, int select)
321 {
322         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
323
324         if(!ob)
325                 return OPERATOR_CANCELLED;
326
327         if(ob->type == OB_MESH) {
328                 EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
329
330                 if(em) {
331                         if(select)
332                                 EM_select_by_material(em, ob->actcol-1);
333                         else
334                                 EM_deselect_by_material(em, ob->actcol-1);
335                 }
336         }
337         else if ELEM(ob->type, OB_CURVE, OB_SURF) {
338                 ListBase *editnurb= ((Curve*)ob->data)->editnurb;
339                 Nurb *nu;
340                 BPoint *bp;
341                 BezTriple *bezt;
342                 int a;
343
344                 for(nu= editnurb->first; nu; nu=nu->next) {
345                         if(nu->mat_nr==ob->actcol-1) {
346                                 if(nu->bezt) {
347                                         a= nu->pntsu;
348                                         bezt= nu->bezt;
349                                         while(a--) {
350                                                 if(bezt->hide==0) {
351                                                         if(select) {
352                                                                 bezt->f1 |= SELECT;
353                                                                 bezt->f2 |= SELECT;
354                                                                 bezt->f3 |= SELECT;
355                                                         }
356                                                         else {
357                                                                 bezt->f1 &= ~SELECT;
358                                                                 bezt->f2 &= ~SELECT;
359                                                                 bezt->f3 &= ~SELECT;
360                                                         }
361                                                 }
362                                                 bezt++;
363                                         }
364                                 }
365                                 else if(nu->bp) {
366                                         a= nu->pntsu*nu->pntsv;
367                                         bp= nu->bp;
368                                         while(a--) {
369                                                 if(bp->hide==0) {
370                                                         if(select) bp->f1 |= SELECT;
371                                                         else bp->f1 &= ~SELECT;
372                                                 }
373                                                 bp++;
374                                         }
375                                 }
376                         }
377                 }
378         }
379
380     WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
381
382         return OPERATOR_FINISHED;
383 }
384
385 static int material_slot_select_exec(bContext *C, wmOperator *op)
386 {
387         return material_slot_de_select(C, 1);
388 }
389
390 void OBJECT_OT_material_slot_select(wmOperatorType *ot)
391 {
392         /* identifiers */
393         ot->name= "Select Material Slot";
394         ot->idname= "OBJECT_OT_material_slot_select";
395         
396         /* api callbacks */
397         ot->exec= material_slot_select_exec;
398
399         /* flags */
400         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
401 }
402
403 static int material_slot_deselect_exec(bContext *C, wmOperator *op)
404 {
405         return material_slot_de_select(C, 0);
406 }
407
408 void OBJECT_OT_material_slot_deselect(wmOperatorType *ot)
409 {
410         /* identifiers */
411         ot->name= "Deselect Material Slot";
412         ot->idname= "OBJECT_OT_material_slot_deselect";
413         
414         /* api callbacks */
415         ot->exec= material_slot_deselect_exec;
416
417         /* flags */
418         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
419 }
420
421 /********************** new material operator *********************/
422
423 static int new_material_exec(bContext *C, wmOperator *op)
424 {
425         Material *ma= CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
426         Object *ob;
427         PointerRNA ptr;
428         int index;
429
430         /* add or copy material */
431         if(ma)
432                 ma= copy_material(ma);
433         else
434                 ma= add_material("Material");
435
436         ma->id.us--; /* compensating for us++ in assign_material */
437
438         /* attempt to assign to material slot */
439         ptr= CTX_data_pointer_get_type(C, "material_slot", &RNA_MaterialSlot);
440
441         if(ptr.data) {
442                 ob= ptr.id.data;
443                 index= (Material**)ptr.data - ob->mat;
444
445                 assign_material(ob, ma, index+1);
446
447                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
448         }
449
450         WM_event_add_notifier(C, NC_MATERIAL|NA_ADDED, ma);
451         
452         return OPERATOR_FINISHED;
453 }
454
455 void MATERIAL_OT_new(wmOperatorType *ot)
456 {
457         /* identifiers */
458         ot->name= "New Material";
459         ot->idname= "MATERIAL_OT_new";
460         
461         /* api callbacks */
462         ot->exec= new_material_exec;
463
464         /* flags */
465         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
466 }
467
468 /********************** new texture operator *********************/
469
470 static int new_texture_exec(bContext *C, wmOperator *op)
471 {
472         Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
473         ID *id;
474         MTex *mtex;
475         PointerRNA ptr;
476
477         /* add or copy texture */
478         if(tex)
479                 tex= copy_texture(tex);
480         else
481                 tex= add_texture("Texture");
482
483         id_us_min(&tex->id);
484
485         /* attempt to assign to texture slot */
486         ptr= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot);
487
488         if(ptr.data) {
489                 id= ptr.id.data;
490                 mtex= ptr.data;
491
492                 if(mtex) {
493                         if(mtex->tex)
494                                 id_us_min(&mtex->tex->id);
495                         mtex->tex= tex;
496                         id_us_plus(&tex->id);
497                 }
498
499                 /* XXX nodes, notifier .. */
500         }
501
502         WM_event_add_notifier(C, NC_TEXTURE|NA_ADDED, tex);
503         
504         return OPERATOR_FINISHED;
505 }
506
507 void TEXTURE_OT_new(wmOperatorType *ot)
508 {
509         /* identifiers */
510         ot->name= "New Texture";
511         ot->idname= "TEXTURE_OT_new";
512         
513         /* api callbacks */
514         ot->exec= new_texture_exec;
515
516         /* flags */
517         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
518 }
519
520 /********************** new world operator *********************/
521
522 static int new_world_exec(bContext *C, wmOperator *op)
523 {
524         Scene *scene= CTX_data_scene(C);
525         World *wo= CTX_data_pointer_get_type(C, "world", &RNA_World).data;
526
527         /* add or copy world */
528         if(wo)
529                 wo= copy_world(wo);
530         else
531                 wo= add_world("World");
532
533         /* assign to scene */
534         if(scene->world)
535                 id_us_min(&scene->world->id);
536         scene->world= wo;
537
538         WM_event_add_notifier(C, NC_WORLD|NA_ADDED, wo);
539         
540         return OPERATOR_FINISHED;
541 }
542
543 void WORLD_OT_new(wmOperatorType *ot)
544 {
545         /* identifiers */
546         ot->name= "New World";
547         ot->idname= "WORLD_OT_new";
548         
549         /* api callbacks */
550         ot->exec= new_world_exec;
551
552         /* flags */
553         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
554 }
555
556
557
558 /********************** particle system slot operators *********************/
559
560 static int particle_system_add_exec(bContext *C, wmOperator *op)
561 {
562         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
563         Scene *scene = CTX_data_scene(C);
564
565         if(!scene || !ob)
566                 return OPERATOR_CANCELLED;
567
568         object_add_particle_system(scene, ob);
569         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
570         
571         return OPERATOR_FINISHED;
572 }
573
574 void OBJECT_OT_particle_system_add(wmOperatorType *ot)
575 {
576         /* identifiers */
577         ot->name= "Add Particle System Slot";
578         ot->idname= "OBJECT_OT_particle_system_add";
579         
580         /* api callbacks */
581         ot->exec= particle_system_add_exec;
582
583         /* flags */
584         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
585 }
586
587 static int particle_system_remove_exec(bContext *C, wmOperator *op)
588 {
589         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
590         Scene *scene = CTX_data_scene(C);
591
592         if(!scene || !ob)
593                 return OPERATOR_CANCELLED;
594
595         object_remove_particle_system(scene, ob);
596         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
597         
598         return OPERATOR_FINISHED;
599 }
600
601 void OBJECT_OT_particle_system_remove(wmOperatorType *ot)
602 {
603         /* identifiers */
604         ot->name= "Remove Particle System Slot";
605         ot->idname= "OBJECT_OT_particle_system_remove";
606         
607         /* api callbacks */
608         ot->exec= particle_system_remove_exec;
609
610         /* flags */
611         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
612 }
613
614 /********************** new particle settings operator *********************/
615
616 static int new_particle_settings_exec(bContext *C, wmOperator *op)
617 {
618         Scene *scene = CTX_data_scene(C);
619         Main *bmain= CTX_data_main(C);
620         ParticleSystem *psys;
621         ParticleSettings *part = NULL;
622         Object *ob;
623         PointerRNA ptr;
624
625         ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
626
627         psys = ptr.data;
628
629         /* add or copy particle setting */
630         if(psys->part)
631                 part= psys_copy_settings(psys->part);
632         else
633                 part= psys_new_settings("ParticleSettings", bmain);
634
635         ob= ptr.id.data;
636
637         if(psys->part)
638                 psys->part->id.us--;
639
640         psys->part = part;
641
642         psys_check_boid_data(psys);
643
644         DAG_scene_sort(scene);
645         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
646
647         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
648         
649         return OPERATOR_FINISHED;
650 }
651
652 void PARTICLE_OT_new(wmOperatorType *ot)
653 {
654         /* identifiers */
655         ot->name= "New Particle Settings";
656         ot->idname= "PARTICLE_OT_new";
657         
658         /* api callbacks */
659         ot->exec= new_particle_settings_exec;
660
661         /* flags */
662         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
663 }
664
665 /********************** keyed particle target operators *********************/
666
667 static int new_particle_target_exec(bContext *C, wmOperator *op)
668 {
669         Scene *scene = CTX_data_scene(C);
670         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
671         ParticleSystem *psys= ptr.data;
672         Object *ob = ptr.id.data;
673
674         ParticleTarget *pt;
675
676         if(!psys)
677                 return OPERATOR_CANCELLED;
678
679         pt = psys->targets.first;
680         for(; pt; pt=pt->next)
681                 pt->flag &= ~PTARGET_CURRENT;
682
683         pt = MEM_callocN(sizeof(ParticleTarget), "keyed particle target");
684
685         pt->flag |= PTARGET_CURRENT;
686         pt->psys = 1;
687
688         BLI_addtail(&psys->targets, pt);
689
690         DAG_scene_sort(scene);
691         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
692
693         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
694         
695         return OPERATOR_FINISHED;
696 }
697
698 void PARTICLE_OT_new_target(wmOperatorType *ot)
699 {
700         /* identifiers */
701         ot->name= "New Particle Target";
702         ot->idname= "PARTICLE_OT_new_target";
703         
704         /* api callbacks */
705         ot->exec= new_particle_target_exec;
706
707         /* flags */
708         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
709 }
710
711 static int remove_particle_target_exec(bContext *C, wmOperator *op)
712 {
713         Scene *scene = CTX_data_scene(C);
714         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
715         ParticleSystem *psys= ptr.data;
716         Object *ob = ptr.id.data;
717
718         ParticleTarget *pt;
719
720         if(!psys)
721                 return OPERATOR_CANCELLED;
722
723         pt = psys->targets.first;
724         for(; pt; pt=pt->next) {
725                 if(pt->flag & PTARGET_CURRENT) {
726                         BLI_remlink(&psys->targets, pt);
727                         MEM_freeN(pt);
728                         break;
729                 }
730
731         }
732         pt = psys->targets.last;
733
734         if(pt)
735                 pt->flag |= PTARGET_CURRENT;
736
737         DAG_scene_sort(scene);
738         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
739
740         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
741         
742         return OPERATOR_FINISHED;
743 }
744
745 void PARTICLE_OT_remove_target(wmOperatorType *ot)
746 {
747         /* identifiers */
748         ot->name= "Remove Particle Target";
749         ot->idname= "PARTICLE_OT_remove_target";
750         
751         /* api callbacks */
752         ot->exec= remove_particle_target_exec;
753
754         /* flags */
755         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
756 }
757
758 /************************ move up particle target operator *********************/
759
760 static int target_move_up_exec(bContext *C, wmOperator *op)
761 {
762         Scene *scene= CTX_data_scene(C);
763         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
764         ParticleSystem *psys= ptr.data;
765         Object *ob = ptr.id.data;
766         ParticleTarget *pt;
767
768         if(!psys)
769                 return OPERATOR_CANCELLED;
770         
771         pt = psys->targets.first;
772         for(; pt; pt=pt->next) {
773                 if(pt->flag & PTARGET_CURRENT && pt->prev) {
774                         BLI_remlink(&psys->targets, pt);
775                         BLI_insertlink(&psys->targets, pt->prev->prev, pt);
776
777                         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
778                         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
779                         break;
780                 }
781         }
782         
783         return OPERATOR_FINISHED;
784 }
785
786 void PARTICLE_OT_target_move_up(wmOperatorType *ot)
787 {
788         ot->name= "Move Up Target";
789         ot->description= "Move particle target up in the list.";
790         ot->idname= "PARTICLE_OT_target_move_up";
791
792         ot->exec= target_move_up_exec;
793         
794         /* flags */
795         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
796 }
797
798 /************************ move down particle target operator *********************/
799
800 static int target_move_down_exec(bContext *C, wmOperator *op)
801 {
802         Scene *scene= CTX_data_scene(C);
803         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
804         ParticleSystem *psys= ptr.data;
805         Object *ob = ptr.id.data;
806         ParticleTarget *pt;
807
808         if(!psys)
809                 return OPERATOR_CANCELLED;
810         pt = psys->targets.first;
811         for(; pt; pt=pt->next) {
812                 if(pt->flag & PTARGET_CURRENT && pt->next) {
813                         BLI_remlink(&psys->targets, pt);
814                         BLI_insertlink(&psys->targets, pt->next, pt);
815
816                         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
817                         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
818                         break;
819                 }
820         }
821         
822         return OPERATOR_FINISHED;
823 }
824
825 void PARTICLE_OT_target_move_down(wmOperatorType *ot)
826 {
827         ot->name= "Move Down Target";
828         ot->description= "Move particle target down in the list.";
829         ot->idname= "PARTICLE_OT_target_move_down";
830
831         ot->exec= target_move_down_exec;
832         
833         /* flags */
834         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
835 }
836
837 /********************** render layer operators *********************/
838
839 static int render_layer_add_exec(bContext *C, wmOperator *op)
840 {
841         Scene *scene= CTX_data_scene(C);
842
843         scene_add_render_layer(scene);
844         scene->r.actlay= BLI_countlist(&scene->r.layers) - 1;
845
846         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
847         
848         return OPERATOR_FINISHED;
849 }
850
851 void SCENE_OT_render_layer_add(wmOperatorType *ot)
852 {
853         /* identifiers */
854         ot->name= "Add Render Layer";
855         ot->idname= "SCENE_OT_render_layer_add";
856         
857         /* api callbacks */
858         ot->exec= render_layer_add_exec;
859
860         /* flags */
861         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
862 }
863
864 static int render_layer_remove_exec(bContext *C, wmOperator *op)
865 {
866         Scene *scene= CTX_data_scene(C);
867         SceneRenderLayer *rl;
868         int act= scene->r.actlay;
869
870         if(BLI_countlist(&scene->r.layers) <= 1)
871                 return OPERATOR_CANCELLED;
872         
873         rl= BLI_findlink(&scene->r.layers, scene->r.actlay);
874         BLI_remlink(&scene->r.layers, rl);
875         MEM_freeN(rl);
876
877         scene->r.actlay= 0;
878         
879         if(scene->nodetree) {
880                 bNode *node;
881                 for(node= scene->nodetree->nodes.first; node; node= node->next) {
882                         if(node->type==CMP_NODE_R_LAYERS && node->id==NULL) {
883                                 if(node->custom1==act)
884                                         node->custom1= 0;
885                                 else if(node->custom1>act)
886                                         node->custom1--;
887                         }
888                 }
889         }
890
891         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
892         
893         return OPERATOR_FINISHED;
894 }
895
896 void SCENE_OT_render_layer_remove(wmOperatorType *ot)
897 {
898         /* identifiers */
899         ot->name= "Remove Render Layer";
900         ot->idname= "SCENE_OT_render_layer_remove";
901         
902         /* api callbacks */
903         ot->exec= render_layer_remove_exec;
904
905         /* flags */
906         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
907 }
908
909 /********************** toolbox operator *********************/
910
911 static int toolbox_invoke(bContext *C, wmOperator *op, wmEvent *event)
912 {
913         bScreen *sc= CTX_wm_screen(C);
914         SpaceButs *sbuts= CTX_wm_space_buts(C);
915         PointerRNA ptr;
916         uiPopupMenu *pup;
917         uiLayout *layout;
918
919         RNA_pointer_create(&sc->id, &RNA_SpaceButtonsWindow, sbuts, &ptr);
920
921         pup= uiPupMenuBegin(C, "Align", 0);
922         layout= uiPupMenuLayout(pup);
923         uiItemsEnumR(layout, &ptr, "align");
924         uiPupMenuEnd(C, pup);
925
926         return OPERATOR_CANCELLED;
927 }
928
929 void BUTTONS_OT_toolbox(wmOperatorType *ot)
930 {
931         /* identifiers */
932         ot->name= "Toolbox";
933         ot->idname= "BUTTONS_OT_toolbox";
934         
935         /* api callbacks */
936         ot->invoke= toolbox_invoke;
937 }
938
939 /********************** filebrowse operator *********************/
940
941 typedef struct FileBrowseOp {
942         PointerRNA ptr;
943         PropertyRNA *prop;
944 } FileBrowseOp;
945
946 static int file_browse_exec(bContext *C, wmOperator *op)
947 {
948         FileBrowseOp *fbo= op->customdata;
949         char *str;
950         
951         str= RNA_string_get_alloc(op->ptr, "filename", 0, 0);
952         RNA_property_string_set(&fbo->ptr, fbo->prop, str);
953         RNA_property_update(C, &fbo->ptr, fbo->prop);
954         MEM_freeN(str);
955
956         MEM_freeN(op->customdata);
957         return OPERATOR_FINISHED;
958 }
959
960 static int file_browse_cancel(bContext *C, wmOperator *op)
961 {
962         MEM_freeN(op->customdata);
963         op->customdata= NULL;
964
965         return OPERATOR_CANCELLED;
966 }
967
968 static int file_browse_invoke(bContext *C, wmOperator *op, wmEvent *event)
969 {
970         PointerRNA ptr;
971         PropertyRNA *prop;
972         FileBrowseOp *fbo;
973         char *str;
974
975         uiFileBrowseContextProperty(C, &ptr, &prop);
976
977         if(!prop)
978                 return OPERATOR_CANCELLED;
979         
980         fbo= MEM_callocN(sizeof(FileBrowseOp), "FileBrowseOp");
981         fbo->ptr= ptr;
982         fbo->prop= prop;
983         op->customdata= fbo;
984
985         str= RNA_property_string_get_alloc(&ptr, prop, 0, 0);
986         RNA_string_set(op->ptr, "filename", str);
987         MEM_freeN(str);
988
989         WM_event_add_fileselect(C, op); 
990         
991         return OPERATOR_RUNNING_MODAL;
992 }
993
994 void BUTTONS_OT_file_browse(wmOperatorType *ot)
995 {
996         /* identifiers */
997         ot->name= "File Browse";
998         ot->idname= "BUTTONS_OT_file_browse";
999         
1000         /* api callbacks */
1001         ot->invoke= file_browse_invoke;
1002         ot->exec= file_browse_exec;
1003         ot->cancel= file_browse_cancel;
1004
1005         /* properties */
1006         WM_operator_properties_filesel(ot, 0);
1007 }
1008