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