b1ffc7249f4b45ba8868f579c77af551845af55c
[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
76 #include "buttons_intern.h"     // own include
77
78
79 /********************** group operators *********************/
80
81 static int group_add_exec(bContext *C, wmOperator *op)
82 {
83         Main *bmain= CTX_data_main(C);
84         Scene *scene= CTX_data_scene(C);
85         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
86         Base *base;
87         Group *group;
88         int value= RNA_enum_get(op->ptr, "group");
89
90         if(!ob)
91                 return OPERATOR_CANCELLED;
92         
93         base= object_in_scene(ob, scene);
94         if(!base)
95                 return OPERATOR_CANCELLED;
96         
97         if(value == -1)
98                 group= add_group( "Group" );
99         else
100                 group= BLI_findlink(&bmain->group, value);
101
102         if(group) {
103                 add_to_group(group, ob);
104                 ob->flag |= OB_FROMGROUP;
105                 base->flag |= OB_FROMGROUP;
106         }
107
108         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
109         
110         return OPERATOR_FINISHED;
111 }
112
113 static EnumPropertyItem group_items[]= {
114         {-1, "ADD_NEW", 0, "Add New Group", ""},
115         {0, NULL, 0, NULL, NULL}};
116
117 static EnumPropertyItem *group_itemf(bContext *C, PointerRNA *ptr, int *free)
118 {       
119         EnumPropertyItem tmp = {0, "", 0, "", ""};
120         EnumPropertyItem *item= NULL;
121         Main *bmain;
122         Group *group;
123         int a, totitem= 0;
124         
125         if(!C) /* needed for docs */
126                 return group_items;
127         
128         RNA_enum_items_add_value(&item, &totitem, group_items, -1);
129
130         bmain= CTX_data_main(C);
131         if(bmain->group.first)
132                 RNA_enum_item_add_separator(&item, &totitem);
133
134         for(a=0, group=bmain->group.first; group; group=group->id.next, a++) {
135                 tmp.value= a;
136                 tmp.identifier= group->id.name+2;
137                 tmp.name= group->id.name+2;
138                 RNA_enum_item_add(&item, &totitem, &tmp);
139         }
140
141         RNA_enum_item_end(&item, &totitem);
142
143         *free= 1;
144
145         return item;
146 }
147
148 void OBJECT_OT_group_add(wmOperatorType *ot)
149 {
150         PropertyRNA *prop;
151
152         /* identifiers */
153         ot->name= "Add Group";
154         ot->idname= "OBJECT_OT_group_add";
155         
156         /* api callbacks */
157         ot->exec= group_add_exec;
158
159         /* flags */
160         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
161
162         /* properties */
163         prop= RNA_def_enum(ot->srna, "group", group_items, -1, "Group", "Group to add object to.");
164         RNA_def_enum_funcs(prop, group_itemf);
165 }
166
167 static int group_remove_exec(bContext *C, wmOperator *op)
168 {
169         Scene *scene= CTX_data_scene(C);
170         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
171         Group *group= CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
172         Base *base;
173
174         if(!ob || !group)
175                 return OPERATOR_CANCELLED;
176
177         base= object_in_scene(ob, scene);
178         if(!base)
179                 return OPERATOR_CANCELLED;
180
181         rem_from_group(group, ob);
182
183         if(find_group(ob, NULL) == NULL) {
184                 ob->flag &= ~OB_FROMGROUP;
185                 base->flag &= ~OB_FROMGROUP;
186         }
187
188         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
189         
190         return OPERATOR_FINISHED;
191 }
192
193 void OBJECT_OT_group_remove(wmOperatorType *ot)
194 {
195         /* identifiers */
196         ot->name= "Remove Group";
197         ot->idname= "OBJECT_OT_group_remove";
198         
199         /* api callbacks */
200         ot->exec= group_remove_exec;
201
202         /* flags */
203         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
204 }
205
206 /********************** material slot operators *********************/
207
208 static int material_slot_add_exec(bContext *C, wmOperator *op)
209 {
210         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
211
212         if(!ob)
213                 return OPERATOR_CANCELLED;
214
215         object_add_material_slot(ob);
216         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
217         
218         return OPERATOR_FINISHED;
219 }
220
221 void OBJECT_OT_material_slot_add(wmOperatorType *ot)
222 {
223         /* identifiers */
224         ot->name= "Add Material Slot";
225         ot->idname= "OBJECT_OT_material_slot_add";
226         
227         /* api callbacks */
228         ot->exec= material_slot_add_exec;
229
230         /* flags */
231         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
232 }
233
234 static int material_slot_remove_exec(bContext *C, wmOperator *op)
235 {
236         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
237
238         if(!ob)
239                 return OPERATOR_CANCELLED;
240
241         object_remove_material_slot(ob);
242         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
243         
244         return OPERATOR_FINISHED;
245 }
246
247 void OBJECT_OT_material_slot_remove(wmOperatorType *ot)
248 {
249         /* identifiers */
250         ot->name= "Remove Material Slot";
251         ot->idname= "OBJECT_OT_material_slot_remove";
252         
253         /* api callbacks */
254         ot->exec= material_slot_remove_exec;
255
256         /* flags */
257         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
258 }
259
260 static int material_slot_assign_exec(bContext *C, wmOperator *op)
261 {
262         Scene *scene= CTX_data_scene(C);
263         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
264
265         if(!ob)
266                 return OPERATOR_CANCELLED;
267
268         if(ob && ob->actcol>0) {
269                 if(ob->type == OB_MESH) {
270                         EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
271                         EditFace *efa;
272
273                         if(em) {
274                                 for(efa= em->faces.first; efa; efa=efa->next)
275                                         if(efa->f & SELECT)
276                                                 efa->mat_nr= ob->actcol-1;
277                         }
278                 }
279                 else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
280                         ListBase *editnurb= ((Curve*)ob->data)->editnurb;
281                         Nurb *nu;
282
283                         if(editnurb) {
284                                 for(nu= editnurb->first; nu; nu= nu->next)
285                                         if(isNurbsel(nu))
286                                                 nu->mat_nr= nu->charidx= ob->actcol-1;
287                         }
288                 }
289                 else if(ob->type == OB_FONT) {
290                         EditFont *ef= ((Curve*)ob->data)->editfont;
291                 int i, selstart, selend;
292
293                         if(ef && BKE_font_getselection(ob, &selstart, &selend)) {
294                                 for(i=selstart; i<=selend; i++)
295                                         ef->textbufinfo[i].mat_nr = ob->actcol-1;
296                         }
297                 }
298         }
299
300     DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
301     WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
302         
303         return OPERATOR_FINISHED;
304 }
305
306 void OBJECT_OT_material_slot_assign(wmOperatorType *ot)
307 {
308         /* identifiers */
309         ot->name= "Assign Material Slot";
310         ot->idname= "OBJECT_OT_material_slot_assign";
311         
312         /* api callbacks */
313         ot->exec= material_slot_assign_exec;
314
315         /* flags */
316         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
317 }
318
319 static int material_slot_de_select(bContext *C, int select)
320 {
321         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
322
323         if(!ob)
324                 return OPERATOR_CANCELLED;
325
326         if(ob->type == OB_MESH) {
327                 EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
328
329                 if(em) {
330                         if(select)
331                                 EM_select_by_material(em, ob->actcol-1);
332                         else
333                                 EM_deselect_by_material(em, ob->actcol-1);
334                 }
335         }
336         else if ELEM(ob->type, OB_CURVE, OB_SURF) {
337                 ListBase *editnurb= ((Curve*)ob->data)->editnurb;
338                 Nurb *nu;
339                 BPoint *bp;
340                 BezTriple *bezt;
341                 int a;
342
343                 for(nu= editnurb->first; nu; nu=nu->next) {
344                         if(nu->mat_nr==ob->actcol-1) {
345                                 if(nu->bezt) {
346                                         a= nu->pntsu;
347                                         bezt= nu->bezt;
348                                         while(a--) {
349                                                 if(bezt->hide==0) {
350                                                         if(select) {
351                                                                 bezt->f1 |= SELECT;
352                                                                 bezt->f2 |= SELECT;
353                                                                 bezt->f3 |= SELECT;
354                                                         }
355                                                         else {
356                                                                 bezt->f1 &= ~SELECT;
357                                                                 bezt->f2 &= ~SELECT;
358                                                                 bezt->f3 &= ~SELECT;
359                                                         }
360                                                 }
361                                                 bezt++;
362                                         }
363                                 }
364                                 else if(nu->bp) {
365                                         a= nu->pntsu*nu->pntsv;
366                                         bp= nu->bp;
367                                         while(a--) {
368                                                 if(bp->hide==0) {
369                                                         if(select) bp->f1 |= SELECT;
370                                                         else bp->f1 &= ~SELECT;
371                                                 }
372                                                 bp++;
373                                         }
374                                 }
375                         }
376                 }
377         }
378
379     WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
380
381         return OPERATOR_FINISHED;
382 }
383
384 static int material_slot_select_exec(bContext *C, wmOperator *op)
385 {
386         return material_slot_de_select(C, 1);
387 }
388
389 void OBJECT_OT_material_slot_select(wmOperatorType *ot)
390 {
391         /* identifiers */
392         ot->name= "Select Material Slot";
393         ot->idname= "OBJECT_OT_material_slot_select";
394         
395         /* api callbacks */
396         ot->exec= material_slot_select_exec;
397
398         /* flags */
399         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
400 }
401
402 static int material_slot_deselect_exec(bContext *C, wmOperator *op)
403 {
404         return material_slot_de_select(C, 0);
405 }
406
407 void OBJECT_OT_material_slot_deselect(wmOperatorType *ot)
408 {
409         /* identifiers */
410         ot->name= "Deselect Material Slot";
411         ot->idname= "OBJECT_OT_material_slot_deselect";
412         
413         /* api callbacks */
414         ot->exec= material_slot_deselect_exec;
415
416         /* flags */
417         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
418 }
419
420 /********************** new material operator *********************/
421
422 static int new_material_exec(bContext *C, wmOperator *op)
423 {
424         Material *ma= CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
425         Object *ob;
426         PointerRNA ptr;
427         int index;
428
429         /* add or copy material */
430         if(ma)
431                 ma= copy_material(ma);
432         else
433                 ma= add_material("Material");
434
435         ma->id.us--; /* compensating for us++ in assign_material */
436
437         /* attempt to assign to material slot */
438         ptr= CTX_data_pointer_get_type(C, "material_slot", &RNA_MaterialSlot);
439
440         if(ptr.data) {
441                 ob= ptr.id.data;
442                 index= (Material**)ptr.data - ob->mat;
443
444                 assign_material(ob, ma, index+1);
445
446                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
447         }
448
449         WM_event_add_notifier(C, NC_MATERIAL|NA_ADDED, ma);
450         
451         return OPERATOR_FINISHED;
452 }
453
454 void MATERIAL_OT_new(wmOperatorType *ot)
455 {
456         /* identifiers */
457         ot->name= "New Material";
458         ot->idname= "MATERIAL_OT_new";
459         
460         /* api callbacks */
461         ot->exec= new_material_exec;
462
463         /* flags */
464         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
465 }
466
467 /********************** new texture operator *********************/
468
469 static int new_texture_exec(bContext *C, wmOperator *op)
470 {
471         Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
472         ID *id;
473         MTex *mtex;
474         PointerRNA ptr;
475
476         /* add or copy texture */
477         if(tex)
478                 tex= copy_texture(tex);
479         else
480                 tex= add_texture("Texture");
481
482         id_us_min(&tex->id);
483
484         /* attempt to assign to texture slot */
485         ptr= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot);
486
487         if(ptr.data) {
488                 id= ptr.id.data;
489                 mtex= ptr.data;
490
491                 if(mtex) {
492                         if(mtex->tex)
493                                 id_us_min(&mtex->tex->id);
494                         mtex->tex= tex;
495                         id_us_plus(&tex->id);
496                 }
497
498                 /* XXX nodes, notifier .. */
499         }
500
501         WM_event_add_notifier(C, NC_TEXTURE|NA_ADDED, tex);
502         
503         return OPERATOR_FINISHED;
504 }
505
506 void TEXTURE_OT_new(wmOperatorType *ot)
507 {
508         /* identifiers */
509         ot->name= "New Texture";
510         ot->idname= "TEXTURE_OT_new";
511         
512         /* api callbacks */
513         ot->exec= new_texture_exec;
514
515         /* flags */
516         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
517 }
518
519 /********************** new world operator *********************/
520
521 static int new_world_exec(bContext *C, wmOperator *op)
522 {
523         Scene *scene= CTX_data_scene(C);
524         World *wo= CTX_data_pointer_get_type(C, "world", &RNA_World).data;
525
526         /* add or copy world */
527         if(wo)
528                 wo= copy_world(wo);
529         else
530                 wo= add_world("World");
531
532         /* assign to scene */
533         if(scene->world)
534                 id_us_min(&scene->world->id);
535         scene->world= wo;
536
537         WM_event_add_notifier(C, NC_WORLD|NA_ADDED, wo);
538         
539         return OPERATOR_FINISHED;
540 }
541
542 void WORLD_OT_new(wmOperatorType *ot)
543 {
544         /* identifiers */
545         ot->name= "New World";
546         ot->idname= "WORLD_OT_new";
547         
548         /* api callbacks */
549         ot->exec= new_world_exec;
550
551         /* flags */
552         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
553 }
554
555
556
557 /********************** particle system slot operators *********************/
558
559 static int particle_system_add_exec(bContext *C, wmOperator *op)
560 {
561         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
562         Scene *scene = CTX_data_scene(C);
563
564         if(!scene || !ob)
565                 return OPERATOR_CANCELLED;
566
567         object_add_particle_system(scene, ob);
568         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
569         
570         return OPERATOR_FINISHED;
571 }
572
573 void OBJECT_OT_particle_system_add(wmOperatorType *ot)
574 {
575         /* identifiers */
576         ot->name= "Add Particle System Slot";
577         ot->idname= "OBJECT_OT_particle_system_add";
578         
579         /* api callbacks */
580         ot->exec= particle_system_add_exec;
581
582         /* flags */
583         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
584 }
585
586 static int particle_system_remove_exec(bContext *C, wmOperator *op)
587 {
588         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
589         Scene *scene = CTX_data_scene(C);
590
591         if(!scene || !ob)
592                 return OPERATOR_CANCELLED;
593
594         object_remove_particle_system(scene, ob);
595         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
596         
597         return OPERATOR_FINISHED;
598 }
599
600 void OBJECT_OT_particle_system_remove(wmOperatorType *ot)
601 {
602         /* identifiers */
603         ot->name= "Remove Particle System Slot";
604         ot->idname= "OBJECT_OT_particle_system_remove";
605         
606         /* api callbacks */
607         ot->exec= particle_system_remove_exec;
608
609         /* flags */
610         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
611 }
612
613 /********************** new particle settings operator *********************/
614
615 static int new_particle_settings_exec(bContext *C, wmOperator *op)
616 {
617         Scene *scene = CTX_data_scene(C);
618         Main *bmain= CTX_data_main(C);
619         ParticleSystem *psys;
620         ParticleSettings *part = NULL;
621         Object *ob;
622         PointerRNA ptr;
623
624         ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
625
626         psys = ptr.data;
627
628         /* add or copy particle setting */
629         if(psys->part)
630                 part= psys_copy_settings(psys->part);
631         else
632                 part= psys_new_settings("ParticleSettings", bmain);
633
634         ob= ptr.id.data;
635
636         if(psys->part)
637                 psys->part->id.us--;
638
639         psys->part = part;
640
641         psys_check_boid_data(psys);
642
643         DAG_scene_sort(scene);
644         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
645
646         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
647         
648         return OPERATOR_FINISHED;
649 }
650
651 void PARTICLE_OT_new(wmOperatorType *ot)
652 {
653         /* identifiers */
654         ot->name= "New Particle Settings";
655         ot->idname= "PARTICLE_OT_new";
656         
657         /* api callbacks */
658         ot->exec= new_particle_settings_exec;
659
660         /* flags */
661         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
662 }
663
664 /********************** keyed particle target operators *********************/
665
666 static int new_particle_target_exec(bContext *C, wmOperator *op)
667 {
668         Scene *scene = CTX_data_scene(C);
669         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
670         ParticleSystem *psys= ptr.data;
671         Object *ob = ptr.id.data;
672
673         ParticleTarget *pt;
674
675         if(!psys)
676                 return OPERATOR_CANCELLED;
677
678         pt = psys->targets.first;
679         for(; pt; pt=pt->next)
680                 pt->flag &= ~PTARGET_CURRENT;
681
682         pt = MEM_callocN(sizeof(ParticleTarget), "keyed particle target");
683
684         pt->flag |= PTARGET_CURRENT;
685         pt->psys = 1;
686
687         BLI_addtail(&psys->targets, pt);
688
689         DAG_scene_sort(scene);
690         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
691
692         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
693         
694         return OPERATOR_FINISHED;
695 }
696
697 void PARTICLE_OT_new_target(wmOperatorType *ot)
698 {
699         /* identifiers */
700         ot->name= "New Particle Target";
701         ot->idname= "PARTICLE_OT_new_target";
702         
703         /* api callbacks */
704         ot->exec= new_particle_target_exec;
705
706         /* flags */
707         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
708 }
709
710 static int remove_particle_target_exec(bContext *C, wmOperator *op)
711 {
712         Scene *scene = CTX_data_scene(C);
713         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
714         ParticleSystem *psys= ptr.data;
715         Object *ob = ptr.id.data;
716
717         ParticleTarget *pt;
718
719         if(!psys)
720                 return OPERATOR_CANCELLED;
721
722         pt = psys->targets.first;
723         for(; pt; pt=pt->next) {
724                 if(pt->flag & PTARGET_CURRENT) {
725                         BLI_remlink(&psys->targets, pt);
726                         MEM_freeN(pt);
727                         break;
728                 }
729
730         }
731         pt = psys->targets.last;
732
733         if(pt)
734                 pt->flag |= PTARGET_CURRENT;
735
736         DAG_scene_sort(scene);
737         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
738
739         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
740         
741         return OPERATOR_FINISHED;
742 }
743
744 void PARTICLE_OT_remove_target(wmOperatorType *ot)
745 {
746         /* identifiers */
747         ot->name= "Remove Particle Target";
748         ot->idname= "PARTICLE_OT_remove_target";
749         
750         /* api callbacks */
751         ot->exec= remove_particle_target_exec;
752
753         /* flags */
754         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
755 }
756
757 /************************ move up particle target operator *********************/
758
759 static int target_move_up_exec(bContext *C, wmOperator *op)
760 {
761         Scene *scene= CTX_data_scene(C);
762         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
763         ParticleSystem *psys= ptr.data;
764         Object *ob = ptr.id.data;
765         ParticleTarget *pt;
766
767         if(!psys)
768                 return OPERATOR_CANCELLED;
769         
770         pt = psys->targets.first;
771         for(; pt; pt=pt->next) {
772                 if(pt->flag & PTARGET_CURRENT && pt->prev) {
773                         BLI_remlink(&psys->targets, pt);
774                         BLI_insertlink(&psys->targets, pt->prev->prev, pt);
775
776                         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
777                         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
778                         break;
779                 }
780         }
781         
782         return OPERATOR_FINISHED;
783 }
784
785 void PARTICLE_OT_target_move_up(wmOperatorType *ot)
786 {
787         ot->name= "Move Up Target";
788         ot->description= "Move particle target up in the list.";
789         ot->idname= "PARTICLE_OT_target_move_up";
790
791         ot->exec= target_move_up_exec;
792         
793         /* flags */
794         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
795 }
796
797 /************************ move down particle target operator *********************/
798
799 static int target_move_down_exec(bContext *C, wmOperator *op)
800 {
801         Scene *scene= CTX_data_scene(C);
802         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
803         ParticleSystem *psys= ptr.data;
804         Object *ob = ptr.id.data;
805         ParticleTarget *pt;
806
807         if(!psys)
808                 return OPERATOR_CANCELLED;
809         pt = psys->targets.first;
810         for(; pt; pt=pt->next) {
811                 if(pt->flag & PTARGET_CURRENT && pt->next) {
812                         BLI_remlink(&psys->targets, pt);
813                         BLI_insertlink(&psys->targets, pt->next, pt);
814
815                         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
816                         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
817                         break;
818                 }
819         }
820         
821         return OPERATOR_FINISHED;
822 }
823
824 void PARTICLE_OT_target_move_down(wmOperatorType *ot)
825 {
826         ot->name= "Move Down Target";
827         ot->description= "Move particle target down in the list.";
828         ot->idname= "PARTICLE_OT_target_move_down";
829
830         ot->exec= target_move_down_exec;
831         
832         /* flags */
833         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
834 }
835
836 /********************** render layer operators *********************/
837
838 static int render_layer_add_exec(bContext *C, wmOperator *op)
839 {
840         Scene *scene= CTX_data_scene(C);
841
842         scene_add_render_layer(scene);
843         scene->r.actlay= BLI_countlist(&scene->r.layers) - 1;
844
845         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
846         
847         return OPERATOR_FINISHED;
848 }
849
850 void SCENE_OT_render_layer_add(wmOperatorType *ot)
851 {
852         /* identifiers */
853         ot->name= "Add Render Layer";
854         ot->idname= "SCENE_OT_render_layer_add";
855         
856         /* api callbacks */
857         ot->exec= render_layer_add_exec;
858
859         /* flags */
860         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
861 }
862
863 static int render_layer_remove_exec(bContext *C, wmOperator *op)
864 {
865         Scene *scene= CTX_data_scene(C);
866         SceneRenderLayer *rl;
867         int act= scene->r.actlay;
868
869         if(BLI_countlist(&scene->r.layers) <= 1)
870                 return OPERATOR_CANCELLED;
871         
872         rl= BLI_findlink(&scene->r.layers, scene->r.actlay);
873         BLI_remlink(&scene->r.layers, rl);
874         MEM_freeN(rl);
875
876         scene->r.actlay= 0;
877         
878         if(scene->nodetree) {
879                 bNode *node;
880                 for(node= scene->nodetree->nodes.first; node; node= node->next) {
881                         if(node->type==CMP_NODE_R_LAYERS && node->id==NULL) {
882                                 if(node->custom1==act)
883                                         node->custom1= 0;
884                                 else if(node->custom1>act)
885                                         node->custom1--;
886                         }
887                 }
888         }
889
890         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
891         
892         return OPERATOR_FINISHED;
893 }
894
895 void SCENE_OT_render_layer_remove(wmOperatorType *ot)
896 {
897         /* identifiers */
898         ot->name= "Remove Render Layer";
899         ot->idname= "SCENE_OT_render_layer_remove";
900         
901         /* api callbacks */
902         ot->exec= render_layer_remove_exec;
903
904         /* flags */
905         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
906 }
907
908 /********************** toolbox operator *********************/
909
910 static int toolbox_invoke(bContext *C, wmOperator *op, wmEvent *event)
911 {
912         bScreen *sc= CTX_wm_screen(C);
913         SpaceButs *sbuts= CTX_wm_space_buts(C);
914         PointerRNA ptr;
915         uiPopupMenu *pup;
916         uiLayout *layout;
917
918         RNA_pointer_create(&sc->id, &RNA_SpaceButtonsWindow, sbuts, &ptr);
919
920         pup= uiPupMenuBegin(C, "Align", 0);
921         layout= uiPupMenuLayout(pup);
922         uiItemsEnumR(layout, &ptr, "align");
923         uiPupMenuEnd(C, pup);
924
925         return OPERATOR_CANCELLED;
926 }
927
928 void BUTTONS_OT_toolbox(wmOperatorType *ot)
929 {
930         /* identifiers */
931         ot->name= "Toolbox";
932         ot->idname= "BUTTONS_OT_toolbox";
933         
934         /* api callbacks */
935         ot->invoke= toolbox_invoke;
936 }
937