4751bd7bb3374f04887172004c16a1b5c212fd4c
[blender-staging.git] / source / blender / editors / physics / editparticle.c
1 /*
2  * $Id: editparticle.c $
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) 2007 by Janne Karhu.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <stdlib.h>
31 #include <math.h>
32 #include <string.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_scene_types.h"
37 #include "DNA_mesh_types.h"
38 #include "DNA_meshdata_types.h"
39 #include "DNA_modifier_types.h"
40 #include "DNA_object_force.h"
41 #include "DNA_object_types.h"
42 #include "DNA_vec_types.h"
43 #include "DNA_userdef_types.h"
44 #include "DNA_view3d_types.h"
45 #include "DNA_screen_types.h"
46 #include "DNA_space_types.h"
47 #include "DNA_windowmanager_types.h"
48
49 #include "BKE_DerivedMesh.h"
50 #include "BKE_depsgraph.h"
51
52 #include "BKE_context.h"
53 #include "BKE_global.h"
54 #include "BKE_object.h"
55 #include "BKE_mesh.h"
56 #include "BKE_modifier.h"
57 #include "BKE_particle.h"
58 #include "BKE_report.h"
59 #include "BKE_scene.h"
60 #include "BKE_utildefines.h" 
61
62 #include "BLI_arithb.h"
63 #include "BLI_blenlib.h"
64 #include "BLI_dynstr.h"
65 #include "BLI_kdtree.h"
66 #include "BLI_rand.h"
67
68 #include "PIL_time.h"
69
70 #include "BIF_gl.h"
71 #include "BIF_glutil.h"
72
73 #include "ED_particle.h"
74 #include "ED_view3d.h"
75
76 #include "UI_interface.h"
77 #include "UI_resources.h"
78
79 #include "WM_api.h"
80 #include "WM_types.h"
81
82 #include "RNA_access.h"
83 #include "RNA_define.h"
84
85 #include "physics_intern.h"
86
87 static void ParticleUndo_clear(ParticleSystem *psys);
88
89 #define LOOP_PARTICLES(i,pa) for(i=0, pa=psys->particles; i<totpart; i++, pa++)
90 #define LOOP_KEYS(k,key) if(psys->edit)for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++)
91
92 /* XXX */
93 static void error() {}
94 static int lasso_inside() {return 0;}
95 static void *mesh_get_x_mirror_faces() {return NULL;}
96
97 #define RADIALCONTROL_SIZE              0
98 #define RADIALCONTROL_STRENGTH  0
99 #define RADIALCONTROL_NONE              0
100 /* XXX */
101
102
103 /**************************** utilities *******************************/
104
105 static int PE_poll(bContext *C)
106 {
107         Scene *scene= CTX_data_scene(C);
108         Object *ob= CTX_data_active_object(C);
109         ParticleSystem *psys;
110
111         if(!scene || !ob)
112                 return 0;
113         
114         psys= PE_get_current(scene, ob);
115
116         return (psys && psys->edit && (G.f & G_PARTICLEEDIT));
117 }
118
119 static int PE_poll_3dview(bContext *C)
120 {
121         Scene *scene= CTX_data_scene(C);
122         Object *ob= CTX_data_active_object(C);
123         ParticleSystem *psys;
124
125         if(!scene || !ob || !CTX_wm_region_view3d(C))
126                 return 0;
127         
128         psys= PE_get_current(scene, ob);
129
130         return (psys && psys->edit && (G.f & G_PARTICLEEDIT));
131 }
132
133 void PE_free_particle_edit(ParticleSystem *psys)
134 {
135         ParticleEdit *edit=psys->edit;
136         int i, totpart=psys->totpart;
137
138         if(edit==0) return;
139
140         ParticleUndo_clear(psys);
141
142         if(edit->keys) {
143                 for(i=0; i<totpart; i++) {
144                         if(edit->keys[i])
145                                 MEM_freeN(edit->keys[i]);
146                 }
147
148                 MEM_freeN(edit->keys);
149         }
150
151         if(edit->mirror_cache)
152                 MEM_freeN(edit->mirror_cache);
153
154         if(edit->emitter_cosnos) {
155                 MEM_freeN(edit->emitter_cosnos);
156                 edit->emitter_cosnos= 0;
157         }
158
159         if(edit->emitter_field) {
160                 BLI_kdtree_free(edit->emitter_field);
161                 edit->emitter_field= 0;
162         }
163
164         MEM_freeN(edit);
165
166         psys->edit= NULL;
167 }
168
169 /************************************************/
170 /*                      Edit Mode Helpers                                       */
171 /************************************************/
172
173 int PE_can_edit(ParticleSystem *psys)
174 {
175         return (psys && psys->edit && (G.f & G_PARTICLEEDIT));
176 }
177
178 ParticleEditSettings *PE_settings(Scene *scene)
179 {
180         return &scene->toolsettings->particle;
181 }
182
183 void PE_change_act(void *ob_v, void *act_v)
184 {
185         Scene *scene= NULL; // XXX
186         Object *ob= ob_v;
187         ParticleSystem *psys;
188         short act= *((short*)act_v) - 1;
189
190         if((psys=psys_get_current(ob)))
191                 psys->flag &= ~PSYS_CURRENT;
192
193         if(act>=0) {
194                 if((psys=BLI_findlink(&ob->particlesystem,act))) {
195                         psys->flag |= PSYS_CURRENT;
196
197                         if(psys_check_enabled(ob, psys)) {
198                                 if(G.f & G_PARTICLEEDIT && !psys->edit)
199                                         PE_create_particle_edit(scene, ob, psys);
200                                 PE_recalc_world_cos(ob, psys);
201                         }
202                 }
203         }
204 }
205
206 void PE_change_act_psys(Scene *scene, Object *ob, ParticleSystem *psys)
207 {
208         ParticleSystem *p;
209         
210         if((p=psys_get_current(ob)))
211                 p->flag &= ~PSYS_CURRENT;
212         
213         psys->flag |= PSYS_CURRENT;
214         
215         if(psys_check_enabled(ob, psys)) {
216                 if(G.f & G_PARTICLEEDIT && !psys->edit)
217                         PE_create_particle_edit(scene, ob, psys);
218                 PE_recalc_world_cos(ob, psys);
219         }
220 }
221
222 /* always gets atleast the first particlesystem even if PSYS_CURRENT flag is not set */
223 ParticleSystem *PE_get_current(Scene *scene, Object *ob)
224 {
225         ParticleSystem *psys;
226
227         if(ob==NULL)
228                 return NULL;
229
230         psys= ob->particlesystem.first;
231         while(psys) {
232                 if(psys->flag & PSYS_CURRENT)
233                         break;
234                 psys=psys->next;
235         }
236
237         if(psys==NULL && ob->particlesystem.first) {
238                 psys=ob->particlesystem.first;
239                 psys->flag |= PSYS_CURRENT;
240         }
241
242         if(psys && psys_check_enabled(ob, psys)) // XXX && (ob == scene->obact) && (G.f & G_PARTICLEEDIT))
243                 if(psys->part->type == PART_HAIR && psys->flag & PSYS_EDITED)
244                         if(psys->edit == NULL)
245                                 PE_create_particle_edit(scene, ob, psys);
246
247         return psys;
248 }
249
250 /* returns -1 if no system has PSYS_CURRENT flag */
251 short PE_get_current_num(Object *ob)
252 {
253         short num=0;
254         ParticleSystem *psys= ob->particlesystem.first;
255
256         while(psys) {
257                 if(psys->flag & PSYS_CURRENT)
258                         return num;
259                 num++;
260                 psys=psys->next;
261         }
262
263         return -1;
264 }
265
266 void PE_hide_keys_time(Scene *scene, ParticleSystem *psys, float cfra)
267 {
268         ParticleData *pa;
269         ParticleEditKey *key;
270         ParticleEditSettings *pset=PE_settings(scene);
271         int i, k, totpart=psys->totpart;
272
273         if(pset->draw_timed && scene->selectmode==SCE_SELECT_POINT) {
274                 LOOP_PARTICLES(i,pa) {
275                         LOOP_KEYS(k,key) {
276                                 if(fabs(cfra-*key->time) < pset->draw_timed)
277                                         key->flag &= ~PEK_HIDE;
278                                 else {
279                                         key->flag |= PEK_HIDE;
280                                         key->flag &= ~PEK_SELECT;
281                                 }
282                         }
283                 }
284         }
285         else {
286                 LOOP_PARTICLES(i,pa) {
287                         LOOP_KEYS(k,key) {
288                                 key->flag &= ~PEK_HIDE;
289                         }
290                 }
291         }
292 }
293
294 /****************** common struct passed to callbacks ******************/
295
296 typedef struct PEData {
297         ViewContext vc;
298         bglMats mats;
299         
300         Scene *scene;
301         Object *ob;
302         DerivedMesh *dm;
303         ParticleSystem *psys;
304
305         short *mval;
306         rcti *rect;
307         float rad;
308         float dist;
309         float dval;
310         int select;
311
312         float *dvec;
313         float combfac;
314         float pufffac;
315         float cutfac;
316         float smoothfac;
317         float weightfac;
318         float growfac;
319
320         int invert;
321         int tot;
322         float vec[3];
323 } PEData;
324
325 static void PE_set_data(bContext *C, PEData *data)
326 {
327         memset(data, 0, sizeof(*data));
328
329         data->scene= CTX_data_scene(C);
330         data->ob= CTX_data_active_object(C);
331         data->psys= PE_get_current(data->scene, data->ob);
332 }
333
334 static void PE_set_view3d_data(bContext *C, PEData *data)
335 {
336         PE_set_data(C, data);
337
338         view3d_set_viewcontext(C, &data->vc);
339         view3d_get_transformation(&data->vc, data->ob, &data->mats);
340 }
341
342 /*************************** selection utilities *******************************/
343
344 static int key_test_depth(PEData *data, float co[3])
345 {
346         View3D *v3d= data->vc.v3d;
347         RegionView3D *rv3d= data->vc.rv3d;
348         double ux, uy, uz;
349         float depth;
350         short wco[3], x,y;
351
352         /* nothing to do */
353         if((v3d->drawtype<=OB_WIRE) || (v3d->flag & V3D_ZBUF_SELECT)==0)
354                 return 1;
355
356         project_short(data->vc.ar, co, wco);
357         
358         if(wco[0] == IS_CLIPPED)
359                 return 0;
360
361         gluProject(co[0],co[1],co[2], data->mats.modelview, data->mats.projection,
362                 (GLint *)data->mats.viewport, &ux, &uy, &uz);
363
364         x=wco[0];
365         y=wco[1];
366
367         // XXX verify ..
368
369         if(rv3d->depths && x<rv3d->depths->w && y<rv3d->depths->h) {
370                 /* the 0.0001 is an experimental threshold to make selecting keys right next to a surface work better */
371                 if((float)uz - 0.0001 > rv3d->depths->depths[y*rv3d->depths->w+x])
372                         return 0;
373                 else
374                         return 1;
375         }
376         else {
377                 x+= (short)data->vc.ar->winrct.xmin;
378                 y+= (short)data->vc.ar->winrct.ymin;
379
380                 glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
381
382                 if((float)uz - 0.0001 > depth)
383                         return 0;
384                 else
385                         return 1;
386         }
387 }
388
389 static int key_inside_circle(PEData *data, float co[3], float *distance)
390 {
391         float dx, dy, dist;
392         short sco[2];
393
394         project_short(data->vc.ar, co, sco);
395         
396         if(sco[0] == IS_CLIPPED)
397                 return 0;
398         
399         dx= data->mval[0] - sco[0];
400         dy= data->mval[1] - sco[1];
401         dist= sqrt(dx*dx + dy*dy);
402
403         if(dist > data->rad)
404                 return 0;
405
406         if(key_test_depth(data, co)) {
407                 if(distance)
408                         *distance=dist;
409
410                 return 1;
411         }
412         
413         return 0;
414 }
415
416 static int key_inside_rect(PEData *data, float co[3])
417 {
418         short sco[2];
419
420         project_short(data->vc.ar, co,sco);
421
422         if(sco[0] == IS_CLIPPED)
423                 return 0;
424         
425         if(sco[0] > data->rect->xmin && sco[0] < data->rect->xmax &&
426            sco[1] > data->rect->ymin && sco[1] < data->rect->ymax)
427                 return key_test_depth(data, co);
428
429         return 0;
430 }
431
432 static int key_inside_test(PEData *data, float co[3])
433 {
434         if(data->mval)
435                 return key_inside_circle(data, co, NULL);
436         else
437                 return key_inside_rect(data, co);
438 }
439
440 static int particle_is_selected(ParticleSystem *psys, ParticleData *pa)
441 {
442         ParticleEditKey *key;
443         int sel, i, k;
444
445         if(pa->flag & PARS_HIDE)
446                 return 0;
447
448         sel= 0;
449         i= pa - psys->particles;
450
451         LOOP_KEYS(k,key)
452                 if(key->flag & PEK_SELECT)
453                         return 1;
454         
455         return 0;
456 }
457
458 /*************************** iterators *******************************/
459
460 typedef void (*ForParticleFunc)(PEData *data, int pa_index);
461 typedef void (*ForKeyFunc)(PEData *data, int pa_index, int key_index);
462 typedef void (*ForKeyMatFunc)(PEData *data, float mat[][4], float imat[][4], int pa_index, int key_index);
463
464 static void for_mouse_hit_keys(PEData *data, ForKeyFunc func, int nearest)
465 {
466         ParticleSystem *psys= data->psys;
467         ParticleEdit *edit= psys->edit;
468         ParticleData *pa;
469         ParticleEditKey *key;
470         int i, k, totpart, nearest_pa, nearest_key;
471         float dist= data->rad;
472
473         /* in path select mode we have no keys */
474         if(data->scene->selectmode==SCE_SELECT_PATH)
475                 return;
476
477         totpart= psys->totpart;
478         nearest_pa= -1;
479         nearest_key= -1;
480
481         LOOP_PARTICLES(i, pa) {
482                 if(pa->flag & PARS_HIDE) continue;
483
484                 if(data->scene->selectmode == SCE_SELECT_END) {
485                         /* only do end keys */
486                         key= edit->keys[i] + pa->totkey-1;
487
488                         if(nearest) {
489                                 if(key_inside_circle(data, key->world_co, &dist)) {
490                                         nearest_pa= i;
491                                         nearest_key= pa->totkey-1;
492                                 }
493                         }
494                         else if(key_inside_test(data, key->world_co))
495                                 func(data, i, pa->totkey-1);
496                 }
497                 else {
498                         /* do all keys */
499                         key= edit->keys[i];
500
501                         LOOP_KEYS(k, key) {
502                                 if(key->flag & PEK_HIDE) continue;
503
504                                 if(nearest) {
505                                         if(key_inside_circle(data, key->world_co, &dist)) {
506                                                 nearest_pa= i;
507                                                 nearest_key= k;
508                                         }
509                                 }
510                                 else if(key_inside_test(data, key->world_co))
511                                         func(data, i, k);
512                         }
513                 }
514         }
515
516         /* do nearest only */
517         if(nearest && nearest_pa > -1)
518                 func(data, nearest_pa, nearest_key);
519 }
520
521 static void foreach_mouse_hit_particle(PEData *data, ForParticleFunc func, int selected)
522 {
523         ParticleSystem *psys= data->psys;
524         ParticleData *pa;
525         ParticleEditKey *key;
526         int i, k, totpart;
527
528         totpart= psys->totpart;
529
530         /* all is selected in path mode */
531         if(data->scene->selectmode==SCE_SELECT_PATH)
532                 selected=0;
533
534         LOOP_PARTICLES(i, pa) {
535                 if(pa->flag & PARS_HIDE) continue;
536
537                 if(data->scene->selectmode==SCE_SELECT_END) {
538                         /* only do end keys */
539                         key= psys->edit->keys[i] + pa->totkey-1;
540
541                         if(selected==0 || key->flag & PEK_SELECT)
542                                 if(key_inside_circle(data, key->world_co, &data->dist))
543                                         func(data, i);
544                 }
545                 else {
546                         /* do all keys */
547                         LOOP_KEYS(k,key) {
548                                 if(key->flag & PEK_HIDE) continue;
549
550                                 if(selected==0 || key->flag & PEK_SELECT) {
551                                         if(key_inside_circle(data, key->world_co, &data->dist)) {
552                                                 func(data, i);
553                                                 break;
554                                         }
555                                 }
556                         }
557                 }
558         }
559 }
560
561 static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected)
562 {
563         ParticleSystem *psys= data->psys;
564         ParticleData *pa;
565         ParticleEditKey *key;
566         ParticleSystemModifierData *psmd=0;
567         int i, k, totpart;
568         float mat[4][4], imat[4][4];
569
570         psmd= psys_get_modifier(data->ob,psys);
571         totpart= psys->totpart;
572
573         /* all is selected in path mode */
574         if(data->scene->selectmode==SCE_SELECT_PATH)
575                 selected= 0;
576
577         Mat4One(imat);
578         Mat4One(mat);
579
580         LOOP_PARTICLES(i,pa) {
581                 if(pa->flag & PARS_HIDE) continue;
582
583                 psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, pa, mat);
584                 Mat4Invert(imat,mat);
585
586                 if(data->scene->selectmode==SCE_SELECT_END) {
587                         /* only do end keys */
588                         key= psys->edit->keys[i] + pa->totkey-1;
589
590                         if(selected==0 || key->flag & PEK_SELECT)
591                                 if(key_inside_circle(data, key->world_co, &data->dist))
592                                         func(data, mat, imat, i, pa->totkey-1);
593                 }
594                 else {
595                         /* do all keys */
596                         LOOP_KEYS(k,key) {
597                                 if(key->flag&PEK_HIDE) continue;
598
599                                 if(selected==0 || key->flag & PEK_SELECT)
600                                         if(key_inside_circle(data, key->world_co, &data->dist))
601                                                 func(data, mat, imat, i, k);
602                         }
603                 }
604         }
605 }
606
607 static void foreach_selected_particle(PEData *data, ForParticleFunc func)
608 {
609         ParticleSystem *psys= data->psys;
610         ParticleData *pa;
611         int i, totpart;
612
613         totpart= psys->totpart;
614
615         LOOP_PARTICLES(i,pa)
616                 if(particle_is_selected(psys, pa))
617                         func(data, i);
618 }
619
620 static void foreach_selected_key(PEData *data, ForKeyFunc func)
621 {
622         ParticleSystem *psys= data->psys;
623         ParticleData *pa;
624         ParticleEditKey *key;
625         int i, k, totpart;
626
627         totpart= psys->totpart;
628
629         LOOP_PARTICLES(i,pa) {
630                 if(pa->flag & PARS_HIDE) continue;
631
632                 key= psys->edit->keys[i];
633
634                 LOOP_KEYS(k,key)
635                         if(key->flag & PEK_SELECT)
636                                 func(data, i, k);
637         }
638 }
639
640 void PE_foreach_particle(PEData *data, ForParticleFunc func)
641 {
642         ParticleSystem *psys= data->psys;
643         int i, totpart;
644
645         totpart= psys->totpart;
646
647         for(i=0; i<totpart; i++)
648                 func(data, i);
649 }
650
651 static int count_selected_keys(Scene *scene, ParticleSystem *psys)
652 {
653         ParticleData *pa;
654         ParticleEditKey *key;
655         int i, k, totpart, sel= 0;
656
657         totpart= psys->totpart;
658
659         LOOP_PARTICLES(i,pa) {
660                 if(pa->flag & PARS_HIDE) continue;
661
662                 key= psys->edit->keys[i];
663
664                 if(scene->selectmode==SCE_SELECT_POINT) {
665                         for(k=0; k<pa->totkey; k++,key++)
666                                 if(key->flag & PEK_SELECT)
667                                         sel++;
668                 }
669                 else if(scene->selectmode==SCE_SELECT_END) {
670                         key += pa->totkey-1;
671
672                         if(key->flag & PEK_SELECT)
673                                 sel++;
674                 }
675         }
676
677         return sel;
678 }
679
680 /************************************************/
681 /*                      Particle Edit Mirroring                         */
682 /************************************************/
683
684 static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
685 {
686         ParticleEdit *edit;
687         ParticleData *pa;
688         ParticleSystemModifierData *psmd;
689         KDTree *tree;
690         KDTreeNearest nearest;
691         float mat[4][4], co[3];
692         int i, index, totpart;
693
694         edit= psys->edit;
695         psmd= psys_get_modifier(ob, psys);
696         totpart= psys->totpart;
697
698         tree= BLI_kdtree_new(totpart);
699
700         /* insert particles into kd tree */
701         LOOP_PARTICLES(i,pa) {
702                 psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat);
703                 VECCOPY(co, pa->hair[0].co);
704                 Mat4MulVecfl(mat, co);
705                 BLI_kdtree_insert(tree, i, co, NULL);
706         }
707
708         BLI_kdtree_balance(tree);
709
710         /* lookup particles and set in mirror cache */
711         if(!edit->mirror_cache)
712                 edit->mirror_cache= MEM_callocN(sizeof(int)*totpart, "PE mirror cache");
713         
714         LOOP_PARTICLES(i,pa) {
715                 psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat);
716                 VECCOPY(co, pa->hair[0].co);
717                 Mat4MulVecfl(mat, co);
718                 co[0]= -co[0];
719
720                 index= BLI_kdtree_find_nearest(tree, co, NULL, &nearest);
721
722                 /* this needs a custom threshold still, duplicated for editmode mirror */
723                 if(index != -1 && index != i && (nearest.dist <= 0.0002f))
724                         edit->mirror_cache[i]= index;
725                 else
726                         edit->mirror_cache[i]= -1;
727         }
728
729         /* make sure mirrors are in two directions */
730         LOOP_PARTICLES(i,pa) {
731                 if(edit->mirror_cache[i]) {
732                         index= edit->mirror_cache[i];
733                         if(edit->mirror_cache[index] != i)
734                                 edit->mirror_cache[i]= -1;
735                 }
736         }
737
738         BLI_kdtree_free(tree);
739 }
740
741 static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys, ParticleData *pa, ParticleData *mpa)
742 {
743         HairKey *hkey, *mhkey;
744         ParticleEditKey *key, *mkey;
745         ParticleEdit *edit;
746         float mat[4][4], mmat[4][4], immat[4][4];
747         int i, mi, k;
748
749         edit= psys->edit;
750         i= pa - psys->particles;
751
752         /* find mirrored particle if needed */
753         if(!mpa) {
754                 if(!edit->mirror_cache)
755                         PE_update_mirror_cache(ob, psys);
756
757                 mi= edit->mirror_cache[i];
758                 if(mi == -1)
759                         return;
760                 mpa= psys->particles + mi;
761         }
762         else
763                 mi= mpa - psys->particles;
764
765         /* make sure they have the same amount of keys */
766         if(pa->totkey != mpa->totkey) {
767                 if(mpa->hair) MEM_freeN(mpa->hair);
768                 if(edit->keys[mi]) MEM_freeN(edit->keys[mi]);
769
770                 mpa->hair= MEM_dupallocN(pa->hair);
771                 edit->keys[mi]= MEM_dupallocN(edit->keys[i]);
772                 mpa->totkey= pa->totkey;
773
774                 mhkey= mpa->hair;
775                 mkey= edit->keys[mi];
776                 for(k=0; k<mpa->totkey; k++, mkey++, mhkey++) {
777                         mkey->co= mhkey->co;
778                         mkey->time= &mhkey->time;
779                         mkey->flag &= PEK_SELECT;
780                 }
781         }
782
783         /* mirror positions and tags */
784         psys_mat_hair_to_orco(ob, dm, psys->part->from, pa, mat);
785         psys_mat_hair_to_orco(ob, dm, psys->part->from, mpa, mmat);
786         Mat4Invert(immat, mmat);
787
788         hkey=pa->hair;
789         mhkey=mpa->hair;
790         key= edit->keys[i];
791         mkey= edit->keys[mi];
792         for(k=0; k<pa->totkey; k++, hkey++, mhkey++, key++, mkey++) {
793                 VECCOPY(mhkey->co, hkey->co);
794                 Mat4MulVecfl(mat, mhkey->co);
795                 mhkey->co[0]= -mhkey->co[0];
796                 Mat4MulVecfl(immat, mhkey->co);
797
798                 if(key->flag & PEK_TAG)
799                         mkey->flag |= PEK_TAG;
800         }
801
802         if(pa->flag & PARS_TAG)
803                 mpa->flag |= PARS_TAG;
804         if(pa->flag & PARS_EDIT_RECALC)
805                 mpa->flag |= PARS_EDIT_RECALC;
806 }
807
808 static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
809 {
810         ParticleEdit *edit;
811         ParticleData *pa;
812         ParticleSystemModifierData *psmd;
813         int i, totpart;
814
815         edit= psys->edit;
816         psmd= psys_get_modifier(ob, psys);
817         totpart= psys->totpart;
818
819         /* we delay settings the PARS_EDIT_RECALC for mirrored particles
820          * to avoid doing mirror twice */
821         LOOP_PARTICLES(i,pa) {
822                 if(pa->flag & PARS_EDIT_RECALC) {
823                         PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
824
825                         if(edit->mirror_cache[i] != -1)
826                                 psys->particles[edit->mirror_cache[i]].flag &= ~PARS_EDIT_RECALC;
827                 }
828         }
829
830         LOOP_PARTICLES(i,pa)
831                 if(pa->flag & PARS_EDIT_RECALC)
832                         if(edit->mirror_cache[i] != -1)
833                                 psys->particles[edit->mirror_cache[i]].flag |= PARS_EDIT_RECALC;
834
835         edit->totkeys= psys_count_keys(psys);
836 }
837
838 /************************************************/
839 /*                      Edit Calculation                                        */
840 /************************************************/
841 /* tries to stop edited particles from going through the emitter's surface */
842 static void pe_deflect_emitter(Scene *scene, Object *ob, ParticleSystem *psys)
843 {
844         ParticleEdit *edit;
845         ParticleData *pa;
846         ParticleEditKey *key;
847         ParticleEditSettings *pset= PE_settings(scene);
848         ParticleSystemModifierData *psmd= psys_get_modifier(ob,psys);
849         int i, k, totpart,index;
850         float *vec, *nor, dvec[3], dot, dist_1st;
851         float hairimat[4][4], hairmat[4][4];
852
853         if(psys==0)
854                 return;
855
856         if((pset->flag & PE_DEFLECT_EMITTER)==0)
857                 return;
858
859         edit=psys->edit;
860         totpart=psys->totpart;
861
862         LOOP_PARTICLES(i,pa) {
863                 if(!(pa->flag & PARS_EDIT_RECALC))
864                         continue;
865                 
866                 psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, hairmat);
867                 
868                 LOOP_KEYS(k,key) {
869                         Mat4MulVecfl(hairmat, key->co);
870                 }
871         //}
872
873         //LOOP_PARTICLES(i,pa) {
874                 key=psys->edit->keys[i]+1;
875
876                 dist_1st=VecLenf((key-1)->co,key->co);
877                 dist_1st*=0.75f*pset->emitterdist;
878
879                 for(k=1; k<pa->totkey; k++, key++) {
880                         index= BLI_kdtree_find_nearest(edit->emitter_field,key->co,NULL,NULL);
881                         
882                         vec=edit->emitter_cosnos +index*6;
883                         nor=vec+3;
884
885                         VecSubf(dvec, key->co, vec);
886
887                         dot=Inpf(dvec,nor);
888                         VECCOPY(dvec,nor);
889
890                         if(dot>0.0f) {
891                                 if(dot<dist_1st) {
892                                         Normalize(dvec);
893                                         VecMulf(dvec,dist_1st-dot);
894                                         VecAddf(key->co,key->co,dvec);
895                                 }
896                         }
897                         else {
898                                 Normalize(dvec);
899                                 VecMulf(dvec,dist_1st-dot);
900                                 VecAddf(key->co,key->co,dvec);
901                         }
902                         if(k==1)
903                                 dist_1st*=1.3333f;
904                 }
905         //}
906
907         //LOOP_PARTICLES(i,pa) {
908                 
909                 Mat4Invert(hairimat,hairmat);
910
911                 LOOP_KEYS(k,key) {
912                         Mat4MulVecfl(hairimat, key->co);
913                 }
914         }
915 }
916 /* force set distances between neighbouring keys */
917 void PE_apply_lengths(Scene *scene, ParticleSystem *psys)
918 {
919         ParticleEdit *edit;
920         ParticleData *pa;
921         ParticleEditKey *key;
922         ParticleEditSettings *pset=PE_settings(scene);
923         int i, k, totpart;
924         float dv1[3];
925
926         if(psys==0)
927                 return;
928
929         if((pset->flag & PE_KEEP_LENGTHS)==0)
930                 return;
931
932         edit=psys->edit;
933         totpart=psys->totpart;
934
935         LOOP_PARTICLES(i,pa) {
936                 if(!(pa->flag & PARS_EDIT_RECALC))
937                         continue;
938                 
939                 for(k=1, key=edit->keys[i] + 1; k<pa->totkey; k++, key++) {
940                         VecSubf(dv1, key->co, (key - 1)->co);
941                         Normalize(dv1);
942                         VecMulf(dv1, (key - 1)->length);
943                         VecAddf(key->co, (key - 1)->co, dv1);
944                 }
945         }
946 }
947 /* try to find a nice solution to keep distances between neighbouring keys */
948 static void pe_iterate_lengths(Scene *scene, ParticleSystem *psys)
949 {
950         ParticleEdit *edit;
951         ParticleData *pa;
952         ParticleEditKey *key;
953         ParticleEditSettings *pset=PE_settings(scene);
954         int i, j, k, totpart;
955         float tlen;
956         float dv0[3]= {0.0f, 0.0f, 0.0f};
957         float dv1[3]= {0.0f, 0.0f, 0.0f};
958         float dv2[3]= {0.0f, 0.0f, 0.0f};
959
960         if(psys==0)
961                 return;
962
963         if((pset->flag & PE_KEEP_LENGTHS)==0)
964                 return;
965
966         edit=psys->edit;
967         totpart=psys->totpart;
968
969         LOOP_PARTICLES(i,pa) {
970                 if(!(pa->flag & PARS_EDIT_RECALC))
971                         continue;
972
973                 for(j=1; j<pa->totkey; j++) {
974                         float mul= 1.0f / (float)pa->totkey;
975
976                         if(pset->flag & PE_LOCK_FIRST) {
977                                 key= edit->keys[i] + 1;
978                                 k= 1;
979                                 dv1[0]= dv1[1]= dv1[2]= 0.0;
980                         }
981                         else {
982                                 key= edit->keys[i];
983                                 k= 0;
984                                 dv0[0]= dv0[1]= dv0[2]= 0.0;
985                         }
986
987                         for(; k<pa->totkey; k++, key++) {
988                                 if(k) {
989                                         VecSubf(dv0, (key - 1)->co, key->co);
990                                         tlen= Normalize(dv0);
991                                         VecMulf(dv0, (mul * (tlen - (key - 1)->length)));
992                                 }
993
994                                 if(k < pa->totkey - 1) {
995                                         VecSubf(dv2, (key + 1)->co, key->co);
996                                         tlen= Normalize(dv2);
997                                         VecMulf(dv2, mul * (tlen - key->length));
998                                 }
999
1000                                 if(k) {
1001                                         VecAddf((key-1)->co,(key-1)->co,dv1);
1002                                 }
1003
1004                                 VECADD(dv1,dv0,dv2);
1005                         }
1006                 }
1007         }
1008 }
1009 /* set current distances to be kept between neighbouting keys */
1010 static void recalc_lengths(ParticleSystem *psys)
1011 {
1012         ParticleData *pa;
1013         ParticleEditKey *key;
1014         int i, k, totpart;
1015
1016         if(psys==0)
1017                 return;
1018
1019         totpart= psys->totpart;
1020
1021         LOOP_PARTICLES(i,pa) {
1022                 key= psys->edit->keys[i];
1023                 for(k=0; k<pa->totkey-1; k++, key++) {
1024                         key->length= VecLenf(key->co, (key + 1)->co);
1025                 }
1026         }
1027 }
1028 /* calculate and store key locations in world coordinates */
1029 void PE_recalc_world_cos(Object *ob, ParticleSystem *psys)
1030 {
1031         ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
1032         ParticleData *pa;
1033         ParticleEditKey *key;
1034         int i, k, totpart;
1035         float hairmat[4][4];
1036
1037         if(psys==0)
1038                 return;
1039
1040         totpart= psys->totpart;
1041
1042         LOOP_PARTICLES(i,pa) {
1043                 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
1044
1045                 LOOP_KEYS(k,key) {
1046                         VECCOPY(key->world_co,key->co);
1047                         Mat4MulVecfl(hairmat, key->world_co);
1048                 }
1049         }
1050 }
1051 /* calculate a tree for finding nearest emitter's vertice */
1052 static void recalc_emitter_field(Object *ob, ParticleSystem *psys)
1053 {
1054         DerivedMesh *dm=psys_get_modifier(ob,psys)->dm;
1055         ParticleEdit *edit= psys->edit;
1056         MFace *mface;
1057         MVert *mvert;
1058         float *vec, *nor;
1059         int i, totface, totvert;
1060
1061         if(edit->emitter_cosnos)
1062                 MEM_freeN(edit->emitter_cosnos);
1063
1064         BLI_kdtree_free(edit->emitter_field);
1065
1066         totface=dm->getNumFaces(dm);
1067         totvert=dm->getNumVerts(dm);
1068
1069         edit->emitter_cosnos=MEM_callocN(totface*6*sizeof(float),"emitter cosnos");
1070
1071         edit->emitter_field= BLI_kdtree_new(totface);
1072
1073         vec=edit->emitter_cosnos;
1074         nor=vec+3;
1075
1076         mvert=dm->getVertDataArray(dm,CD_MVERT);
1077         for(i=0; i<totface; i++, vec+=6, nor+=6) {
1078                 mface=dm->getFaceData(dm,i,CD_MFACE);
1079
1080                 mvert=dm->getVertData(dm,mface->v1,CD_MVERT);
1081                 VECCOPY(vec,mvert->co);
1082                 VECCOPY(nor,mvert->no);
1083
1084                 mvert=dm->getVertData(dm,mface->v2,CD_MVERT);
1085                 VECADD(vec,vec,mvert->co);
1086                 VECADD(nor,nor,mvert->no);
1087
1088                 mvert=dm->getVertData(dm,mface->v3,CD_MVERT);
1089                 VECADD(vec,vec,mvert->co);
1090                 VECADD(nor,nor,mvert->no);
1091
1092                 if(mface->v4) {
1093                         mvert=dm->getVertData(dm,mface->v4,CD_MVERT);
1094                         VECADD(vec,vec,mvert->co);
1095                         VECADD(nor,nor,mvert->no);
1096                         
1097                         VecMulf(vec,0.25);
1098                 }
1099                 else
1100                         VecMulf(vec,0.3333f);
1101
1102                 Normalize(nor);
1103
1104                 BLI_kdtree_insert(edit->emitter_field, i, vec, NULL);
1105         }
1106
1107         BLI_kdtree_balance(edit->emitter_field);
1108 }
1109
1110 void PE_update_selection(Scene *scene, Object *ob, int useflag)
1111 {
1112         ParticleSystem *psys= PE_get_current(scene, ob);
1113         ParticleEdit *edit= psys->edit;
1114         ParticleEditSettings *pset= PE_settings(scene);
1115         ParticleSettings *part= psys->part;
1116         ParticleData *pa;
1117         HairKey *hkey;
1118         ParticleEditKey *key;
1119         float cfra= CFRA;
1120         int i, k, totpart;
1121
1122         totpart= psys->totpart;
1123
1124         /* flag all particles to be updated if not using flag */
1125         if(!useflag)
1126                 LOOP_PARTICLES(i,pa)
1127                         pa->flag |= PARS_EDIT_RECALC;
1128
1129         /* flush edit key flag to hair key flag to preserve selection 
1130          * on save */
1131         LOOP_PARTICLES(i,pa) {
1132                 key= edit->keys[i];
1133
1134                 for(k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, key++)
1135                         hkey->editflag= key->flag;
1136         }
1137
1138         psys_cache_paths(scene, ob, psys, CFRA, 1);
1139
1140         if(part->childtype && (pset->flag & PE_SHOW_CHILD))
1141                 psys_cache_child_paths(scene, ob, psys, cfra, 1);
1142
1143         /* disable update flag */
1144         LOOP_PARTICLES(i,pa)
1145                 pa->flag &= ~PARS_EDIT_RECALC;
1146 }
1147
1148 void PE_update_object(Scene *scene, Object *ob, int useflag)
1149 {
1150         ParticleSystem *psys= PE_get_current(scene, ob);
1151         ParticleEditSettings *pset= PE_settings(scene);
1152         ParticleSettings *part= psys->part;
1153         ParticleData *pa;
1154         float cfra= CFRA;
1155         int i, totpart= psys->totpart;
1156
1157         /* flag all particles to be updated if not using flag */
1158         if(!useflag)
1159                 LOOP_PARTICLES(i,pa)
1160                         pa->flag |= PARS_EDIT_RECALC;
1161
1162         /* do post process on particle edit keys */
1163         pe_iterate_lengths(scene, psys);
1164         pe_deflect_emitter(scene, ob, psys);
1165         PE_apply_lengths(scene, psys);
1166         if(pset->flag & PE_X_MIRROR)
1167                 PE_apply_mirror(ob,psys);
1168         PE_recalc_world_cos(ob,psys);
1169         PE_hide_keys_time(scene, psys, cfra);
1170
1171         /* regenerate path caches */
1172         psys_cache_paths(scene, ob, psys, cfra, 1);
1173
1174         if(part->childtype && (pset->flag & PE_SHOW_CHILD))
1175                 psys_cache_child_paths(scene, ob, psys, cfra, 1);
1176
1177         /* disable update flag */
1178         LOOP_PARTICLES(i,pa)
1179                 pa->flag &= ~PARS_EDIT_RECALC;
1180 }
1181
1182 /************************ particle edit toggle operator ************************/
1183
1184 /* initialize needed data for bake edit */
1185 void PE_create_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys)
1186 {
1187         ParticleEdit *edit=psys->edit;
1188         ParticleData *pa;
1189         ParticleEditKey *key;
1190         HairKey *hkey;
1191         int i, k, totpart=psys->totpart, alloc=1;
1192
1193         if((psys->flag & PSYS_EDITED)==0)
1194                 return;
1195
1196         if(edit) {
1197                 int newtotkeys= psys_count_keys(psys);
1198                 if(newtotkeys == edit->totkeys)
1199                         alloc=0;
1200         }
1201
1202         if(alloc) {
1203                 if(edit) {
1204                         error("ParticleEdit exists allready! Poke jahka!");
1205                         PE_free_particle_edit(psys);
1206                 }
1207
1208                 edit=psys->edit=MEM_callocN(sizeof(ParticleEdit), "PE_create_particle_edit");
1209
1210                 edit->keys=MEM_callocN(totpart*sizeof(ParticleEditKey*),"ParticleEditKey array");
1211
1212                 LOOP_PARTICLES(i,pa) {
1213                         key= edit->keys[i]= MEM_callocN(pa->totkey*sizeof(ParticleEditKey),"ParticleEditKeys");
1214                         for(k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, key++) {
1215                                 key->co= hkey->co;
1216                                 key->time= &hkey->time;
1217                                 key->flag= hkey->editflag;
1218                         }
1219                 }
1220
1221                 edit->totkeys= psys_count_keys(psys);
1222         }
1223
1224         recalc_lengths(psys);
1225         recalc_emitter_field(ob, psys);
1226         PE_recalc_world_cos(ob, psys);
1227
1228         if(alloc) {
1229                 ParticleUndo_clear(psys);
1230                 PE_undo_push(scene, "Original");
1231         }
1232 }
1233
1234 static int particle_edit_toggle_poll(bContext *C)
1235 {
1236         Scene *scene= CTX_data_scene(C);
1237         Object *ob= CTX_data_active_object(C);
1238
1239         if(!scene || !ob || ob->id.lib)
1240                 return 0;
1241         
1242         return (ob->particlesystem.first != NULL);
1243 }
1244
1245 static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
1246 {
1247         Scene *scene= CTX_data_scene(C);
1248         Object *ob= CTX_data_active_object(C);
1249         ParticleSystem *psys= PE_get_current(scene, ob);
1250         
1251         if(psys==NULL) {
1252                 psys= ob->particlesystem.first;
1253                 psys->flag |= PSYS_CURRENT;
1254         }
1255
1256         if(!(G.f & G_PARTICLEEDIT)) {
1257                 if(psys && psys->part->type == PART_HAIR && psys->flag & PSYS_EDITED) {
1258                         if(psys_check_enabled(ob, psys)) {
1259                                 if(psys->edit==NULL)
1260                                         PE_create_particle_edit(scene, ob, psys);
1261
1262                                 PE_recalc_world_cos(ob, psys);
1263                         }
1264                 }
1265
1266                 G.f |= G_PARTICLEEDIT;
1267                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_PARTICLE, NULL);
1268         }
1269         else {
1270                 G.f &= ~G_PARTICLEEDIT;
1271                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
1272         }
1273
1274         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
1275
1276         return OPERATOR_FINISHED;
1277 }
1278
1279 void PARTICLE_OT_particle_edit_toggle(wmOperatorType *ot)
1280 {
1281         /* identifiers */
1282         ot->name= "Particle Edit Toggle";
1283         ot->idname= "PARTICLE_OT_particle_edit_toggle";
1284         
1285         /* api callbacks */
1286         ot->exec= particle_edit_toggle_exec;
1287         ot->poll= particle_edit_toggle_poll;
1288
1289         /* flags */
1290         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1291 }
1292
1293 /************************************************/
1294 /*                      Edit Selections                                         */
1295 /************************************************/
1296
1297 /*-----selection callbacks-----*/
1298
1299 static void select_key(PEData *data, int pa_index, int key_index)
1300 {
1301         ParticleSystem *psys= data->psys;
1302         ParticleData *pa= psys->particles + pa_index;
1303         ParticleEditKey *key= psys->edit->keys[pa_index] + key_index;
1304
1305         if(data->select)
1306                 key->flag |= PEK_SELECT;
1307         else
1308                 key->flag &= ~PEK_SELECT;
1309
1310         pa->flag |= PARS_EDIT_RECALC;
1311 }
1312
1313 static void select_keys(PEData *data, int pa_index, int key_index)
1314 {
1315         ParticleSystem *psys= data->psys;
1316         ParticleData *pa= psys->particles + pa_index;
1317         ParticleEditKey *key= psys->edit->keys[pa_index];
1318         int k;
1319
1320         for(k=0; k<pa->totkey; k++,key++) {
1321                 if(data->select)
1322                         key->flag |= PEK_SELECT;
1323                 else
1324                         key->flag &= ~PEK_SELECT;
1325         }
1326
1327         pa->flag |= PARS_EDIT_RECALC;
1328 }
1329
1330 static void toggle_key_select(PEData *data, int pa_index, int key_index)
1331 {
1332         ParticleSystem *psys= data->psys;
1333         ParticleData *pa= psys->particles + pa_index;
1334
1335         if(psys->edit->keys[pa_index][key_index].flag&PEK_SELECT)
1336                 psys->edit->keys[pa_index][key_index].flag &= ~PEK_SELECT;
1337         else
1338                 psys->edit->keys[pa_index][key_index].flag |= PEK_SELECT;
1339         
1340         pa->flag |= PARS_EDIT_RECALC;
1341 }
1342
1343 /************************ de select all operator ************************/
1344
1345 static int de_select_all_exec(bContext *C, wmOperator *op)
1346 {
1347         Scene *scene= CTX_data_scene(C);
1348         Object *ob= CTX_data_active_object(C);
1349         ParticleSystem *psys= PE_get_current(scene, ob);
1350         ParticleEdit *edit= 0;
1351         ParticleData *pa;
1352         ParticleEditKey *key;
1353         int i, k, totpart, sel= 0;
1354         
1355         edit= psys->edit;
1356         totpart= psys->totpart;
1357         
1358         LOOP_PARTICLES(i,pa) {
1359                 if(pa->flag & PARS_HIDE) continue;
1360                 LOOP_KEYS(k,key) {
1361                         if(key->flag & PEK_SELECT) {
1362                                 sel= 1;
1363                                 key->flag &= ~PEK_SELECT;
1364                                 pa->flag |= PARS_EDIT_RECALC;
1365                         }
1366                 }
1367         }
1368
1369         if(sel==0) {
1370                 LOOP_PARTICLES(i,pa) {
1371                         if(pa->flag & PARS_HIDE) continue;
1372                         LOOP_KEYS(k,key) {
1373                                 if(!(key->flag & PEK_SELECT)) {
1374                                         key->flag |= PEK_SELECT;
1375                                         pa->flag |= PARS_EDIT_RECALC;
1376                                 }
1377                         }
1378                 }
1379         }
1380
1381         PE_update_selection(scene, ob, 1);
1382         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
1383
1384         return OPERATOR_FINISHED;
1385 }
1386
1387 void PARTICLE_OT_de_select_all(wmOperatorType *ot)
1388 {
1389         /* identifiers */
1390         ot->name= "Select or Deselect All";
1391         ot->idname= "PARTICLE_OT_de_select_all";
1392         
1393         /* api callbacks */
1394         ot->exec= de_select_all_exec;
1395         ot->poll= PE_poll;
1396
1397         /* flags */
1398         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1399 }
1400
1401 /************************ pick select operator ************************/
1402
1403 void PE_mouse_particles(void)
1404 {
1405         bContext *C= NULL; // XXX
1406         PEData data;
1407         Scene *scene= CTX_data_scene(C);
1408         Object *ob= CTX_data_active_object(C);
1409         ParticleSystem *psys= PE_get_current(scene, ob);
1410         ParticleEdit *edit= 0;
1411         ParticleData *pa;
1412         ParticleEditKey *key;
1413         short mval[2];
1414         int i, k, totpart;
1415         int shift= 0; // XXX
1416         
1417         if(!PE_can_edit(psys)) return;
1418
1419         edit= psys->edit;
1420
1421         totpart= psys->totpart;
1422
1423         bglFlush();
1424         glReadBuffer(GL_BACK);
1425         glDrawBuffer(GL_BACK);
1426 //      persp(PERSP_VIEW);
1427
1428         if(shift)
1429                 LOOP_PARTICLES(i,pa) {
1430                         if(pa->flag & PARS_HIDE) continue;
1431                         LOOP_KEYS(k,key) {
1432                                 if(key->flag & PEK_SELECT) {
1433                                         key->flag &= ~PEK_SELECT;
1434                                         pa->flag |= PARS_EDIT_RECALC;
1435                                 }
1436                         }
1437                 }
1438         
1439         // XXX mval
1440
1441         PE_set_view3d_data(C, &data);
1442         data.mval= mval;
1443         data.rad= 75.0f;
1444
1445         for_mouse_hit_keys(&data, toggle_key_select, 1);  /* nearest only */
1446
1447         PE_update_selection(scene, ob, 1);
1448
1449 }
1450
1451 /************************ select first operator ************************/
1452
1453 static void select_root(PEData *data, int pa_index)
1454 {
1455         ParticleSystem *psys= data->psys;
1456
1457         psys->edit->keys[pa_index]->flag |= PEK_SELECT;
1458 }
1459
1460 static int select_first_exec(bContext *C, wmOperator *op)
1461 {
1462         PEData data;
1463
1464         PE_set_data(C, &data);
1465         PE_foreach_particle(&data, select_root);
1466         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob);
1467
1468         return OPERATOR_FINISHED;
1469 }
1470
1471 void PARTICLE_OT_select_first(wmOperatorType *ot)
1472 {
1473         /* identifiers */
1474         ot->name= "Select First";
1475         ot->idname= "PARTICLE_OT_select_first";
1476         
1477         /* api callbacks */
1478         ot->exec= select_first_exec;
1479         ot->poll= PE_poll;
1480
1481         /* flags */
1482         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1483 }
1484
1485 /************************ select last operator ************************/
1486
1487 static void select_tip(PEData *data, int pa_index)
1488 {
1489         ParticleSystem *psys= data->psys;
1490         ParticleData *pa= psys->particles + pa_index;
1491         ParticleEditKey *key= psys->edit->keys[pa_index] + pa->totkey-1;
1492
1493         key->flag |= PEK_SELECT;
1494 }
1495
1496 static int select_last_exec(bContext *C, wmOperator *op)
1497 {
1498         PEData data;
1499
1500         PE_set_data(C, &data);
1501         PE_foreach_particle(&data, select_tip);
1502         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob);
1503
1504         return OPERATOR_FINISHED;
1505 }
1506
1507 void PARTICLE_OT_select_last(wmOperatorType *ot)
1508 {
1509         /* identifiers */
1510         ot->name= "Select Last";
1511         ot->idname= "PARTICLE_OT_select_last";
1512         
1513         /* api callbacks */
1514         ot->exec= select_last_exec;
1515         ot->poll= PE_poll;
1516
1517         /* flags */
1518         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1519 }
1520
1521 /************************ select linked operator ************************/
1522
1523 static int select_linked_exec(bContext *C, wmOperator *op)
1524 {
1525         PEData data;
1526         short mval[2];
1527         int location[2];
1528
1529         RNA_int_get_array(op->ptr, "location", location);
1530         mval[0]= location[0];
1531         mval[1]= location[1];
1532
1533         PE_set_view3d_data(C, &data);
1534         data.mval= mval;
1535         data.rad=75.0f;
1536         data.select= !RNA_boolean_get(op->ptr, "deselect");
1537
1538         for_mouse_hit_keys(&data, select_keys, 1);  /* nearest only */
1539         PE_update_selection(data.scene, data.ob, 1);
1540         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob);
1541
1542         return OPERATOR_FINISHED;
1543 }
1544
1545 static int select_linked_invoke(bContext *C, wmOperator *op, wmEvent *event)
1546 {
1547         ARegion *ar= CTX_wm_region(C);
1548         int location[2];
1549
1550         location[0]= event->x - ar->winrct.xmin;
1551         location[1]= event->y - ar->winrct.ymin;
1552         RNA_int_set_array(op->ptr, "location", location);
1553
1554         return select_linked_exec(C, op);
1555 }
1556
1557 void PARTICLE_OT_select_linked(wmOperatorType *ot)
1558 {
1559         /* identifiers */
1560         ot->name= "Select Linked";
1561         ot->idname= "PARTICLE_OT_select_linked";
1562         
1563         /* api callbacks */
1564         ot->exec= select_linked_exec;
1565         ot->invoke= select_linked_invoke;
1566         ot->poll= PE_poll_3dview;
1567
1568         /* flags */
1569         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1570
1571         /* properties */
1572         RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect linked keys rather than selecting them.");
1573         RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "", 0, 16384);
1574 }
1575
1576 /************************ border select operator ************************/
1577
1578 void PE_border_select(ViewContext *vc, rcti *rect, int select)
1579 {
1580         Scene *scene= vc->scene;
1581         Object *ob= vc->obact;
1582         ParticleSystem *psys= PE_get_current(scene, ob);
1583         PEData data;
1584
1585         if(!PE_can_edit(psys)) return;
1586
1587         memset(&data, 0, sizeof(data));
1588         data.vc= *vc;
1589         data.scene= scene;
1590         data.ob= ob;
1591         data.psys= psys;
1592         data.rect= rect;
1593         data.select= select;
1594
1595         for_mouse_hit_keys(&data, select_key, 0);
1596
1597         PE_update_selection(scene, ob, 1);
1598
1599         /* XXX undo, notifier */
1600         PE_undo_push(scene, "Border Select");
1601 }
1602
1603 /************************ circle select operator ************************/
1604
1605 void PE_circle_select(ViewContext *vc, int selecting, short *mval, float rad)
1606 {
1607         Scene *scene= vc->scene;
1608         Object *ob= vc->obact;
1609         ParticleSystem *psys= PE_get_current(scene, ob);
1610         PEData data;
1611
1612         if(!PE_can_edit(psys)) return;
1613
1614         memset(&data, 0, sizeof(data));
1615         data.vc= *vc;
1616         data.scene= scene;
1617         data.ob= ob;
1618         data.psys= psys;
1619         data.mval=mval;
1620         data.rad=rad;
1621         data.select= selecting;
1622
1623         for_mouse_hit_keys(&data, select_key, 0);
1624
1625         /* XXX undo, notifier */
1626         PE_undo_push(scene, "Circle Select");
1627 }
1628
1629 /************************ lasso select operator ************************/
1630
1631 void PE_lasso_select(ViewContext *vc, short mcords[][2], short moves, short select)
1632 {
1633         Scene *scene= vc->scene;
1634         ARegion *ar= vc->ar;
1635         Object *ob= OBACT;
1636         ParticleSystem *psys= PE_get_current(scene, ob);
1637         ParticleSystemModifierData *psmd;
1638         ParticleEdit *edit;
1639         ParticleData *pa;
1640         ParticleEditKey *key;
1641         float co[3], mat[4][4];
1642         short vertco[2];
1643         int i, k, totpart;
1644
1645         if(!PE_can_edit(psys)) return;
1646
1647         psmd= psys_get_modifier(ob, psys);
1648         edit=psys->edit;
1649         totpart=psys->totpart;
1650
1651         LOOP_PARTICLES(i,pa) {
1652                 if(pa->flag & PARS_HIDE) continue;
1653
1654                 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1655
1656                 if(scene->selectmode==SCE_SELECT_POINT) {
1657                         LOOP_KEYS(k,key) {
1658                                 VECCOPY(co, key->co);
1659                                 Mat4MulVecfl(mat, co);
1660                                 project_short(ar, co, vertco);
1661                                 if((vertco[0] != IS_CLIPPED) && lasso_inside(mcords,moves,vertco[0],vertco[1])) {
1662                                         if(select && !(key->flag & PEK_SELECT)) {
1663                                                 key->flag |= PEK_SELECT;
1664                                                 pa->flag |= PARS_EDIT_RECALC;
1665                                         }
1666                                         else if(key->flag & PEK_SELECT) {
1667                                                 key->flag &= ~PEK_SELECT;
1668                                                 pa->flag |= PARS_EDIT_RECALC;
1669                                         }
1670                                 }
1671                         }
1672                 }
1673                 else if(scene->selectmode==SCE_SELECT_END) {
1674                         key= edit->keys[i] + pa->totkey - 1;
1675
1676                         VECCOPY(co, key->co);
1677                         Mat4MulVecfl(mat, co);
1678                         project_short(ar, co,vertco);
1679                         if((vertco[0] != IS_CLIPPED) && lasso_inside(mcords,moves,vertco[0],vertco[1])) {
1680                                 if(select && !(key->flag & PEK_SELECT)) {
1681                                         key->flag |= PEK_SELECT;
1682                                         pa->flag |= PARS_EDIT_RECALC;
1683                                 }
1684                                 else if(key->flag & PEK_SELECT) {
1685                                         key->flag &= ~PEK_SELECT;
1686                                         pa->flag |= PARS_EDIT_RECALC;
1687                                 }
1688                         }
1689                 }
1690         }
1691
1692         PE_update_selection(scene, ob, 1);
1693
1694         /* XXX undo, notifier */
1695         PE_undo_push(scene, "Lasso select particles");
1696 }
1697
1698 /*************************** hide operator **************************/
1699
1700 static int hide_exec(bContext *C, wmOperator *op)
1701 {
1702         Object *ob= CTX_data_active_object(C);
1703         Scene *scene= CTX_data_scene(C);
1704         ParticleSystem *psys= PE_get_current(scene, ob);
1705         ParticleEdit *edit;
1706         ParticleEditKey *key;
1707         ParticleData *pa;
1708         int i, k, totpart;
1709
1710         edit= psys->edit;
1711         totpart= psys->totpart;
1712         
1713         if(RNA_enum_get(op->ptr, "unselected")) {
1714                 LOOP_PARTICLES(i, pa) {
1715                         if(!particle_is_selected(psys, pa)) {
1716                                 pa->flag |= PARS_HIDE;
1717                                 pa->flag |= PARS_EDIT_RECALC;
1718
1719                                 LOOP_KEYS(k, key)
1720                                         key->flag &= ~PEK_SELECT;
1721                         }
1722                 }
1723         }
1724         else {
1725                 LOOP_PARTICLES(i, pa) {
1726                         if(particle_is_selected(psys, pa)) {
1727                                 pa->flag |= PARS_HIDE;
1728                                 pa->flag |= PARS_EDIT_RECALC;
1729
1730                                 LOOP_KEYS(k, key)
1731                                         key->flag &= ~PEK_SELECT;
1732                         }
1733                 }
1734         }
1735
1736         PE_update_selection(scene, ob, 1);
1737         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
1738
1739         return OPERATOR_FINISHED;
1740 }
1741
1742 void PARTICLE_OT_hide(wmOperatorType *ot)
1743 {
1744         /* identifiers */
1745         ot->name= "Hide Selected";
1746         ot->idname= "PARTICLE_OT_hide";
1747         
1748         /* api callbacks */
1749         ot->exec= hide_exec;
1750         ot->poll= PE_poll;
1751
1752         /* flags */
1753         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1754
1755         /* props */
1756         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected.");
1757 }
1758
1759 /*************************** reveal operator **************************/
1760
1761 static int reveal_exec(bContext *C, wmOperator *op)
1762 {
1763         Object *ob= CTX_data_active_object(C);
1764         Scene *scene= CTX_data_scene(C);
1765         ParticleSystem *psys= PE_get_current(scene, ob);
1766         ParticleEdit *edit;
1767         ParticleEditKey *key;
1768         ParticleData *pa;
1769         int i, k, totpart;
1770
1771         edit= psys->edit;
1772         totpart= psys->totpart;
1773
1774         LOOP_PARTICLES(i, pa) {
1775                 if(pa->flag & PARS_HIDE) {
1776                         pa->flag &= ~PARS_HIDE;
1777                         pa->flag |= PARS_EDIT_RECALC;
1778
1779                         LOOP_KEYS(k, key)
1780                                 key->flag |= PEK_SELECT;
1781                 }
1782         }
1783
1784         PE_update_selection(scene, ob, 1);
1785         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
1786
1787         return OPERATOR_FINISHED;
1788 }
1789
1790 void PARTICLE_OT_reveal(wmOperatorType *ot)
1791 {
1792         /* identifiers */
1793         ot->name= "Reveal";
1794         ot->idname= "PARTICLE_OT_reveal";
1795         
1796         /* api callbacks */
1797         ot->exec= reveal_exec;
1798         ot->poll= PE_poll;
1799
1800         /* flags */
1801         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1802 }
1803
1804 /************************ select less operator ************************/
1805
1806 static void select_less_keys(PEData *data, int pa_index)
1807 {
1808         ParticleSystem *psys= data->psys;
1809         ParticleEdit *edit= psys->edit;
1810         ParticleData *pa= &psys->particles[pa_index];
1811         ParticleEditKey *key;
1812         int k;
1813
1814         for(k=0,key=edit->keys[pa_index]; k<pa->totkey; k++,key++) {
1815                 if((key->flag & PEK_SELECT)==0) continue;
1816
1817                 if(k==0) {
1818                         if(((key+1)->flag&PEK_SELECT)==0)
1819                                 key->flag |= PEK_TO_SELECT;
1820                 }
1821                 else if(k==pa->totkey-1) {
1822                         if(((key-1)->flag&PEK_SELECT)==0)
1823                                 key->flag |= PEK_TO_SELECT;
1824                 }
1825                 else {
1826                         if((((key-1)->flag & (key+1)->flag) & PEK_SELECT)==0)
1827                                 key->flag |= PEK_TO_SELECT;
1828                 }
1829         }
1830
1831         for(k=0,key=edit->keys[pa_index]; k<pa->totkey; k++,key++) {
1832                 if(key->flag&PEK_TO_SELECT)
1833                         key->flag &= ~(PEK_TO_SELECT|PEK_SELECT);
1834         }
1835 }
1836
1837 static int select_less_exec(bContext *C, wmOperator *op)
1838 {
1839         PEData data;
1840
1841         PE_set_data(C, &data);
1842         PE_foreach_particle(&data, select_less_keys);
1843         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob);
1844
1845         return OPERATOR_FINISHED;
1846 }
1847
1848 void PARTICLE_OT_select_less(wmOperatorType *ot)
1849 {
1850         /* identifiers */
1851         ot->name= "Select Less";
1852         ot->idname= "PARTICLE_OT_select_less";
1853         
1854         /* api callbacks */
1855         ot->exec= select_less_exec;
1856         ot->poll= PE_poll;
1857
1858         /* flags */
1859         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1860 }
1861
1862 /************************ select more operator ************************/
1863
1864 static void select_more_keys(PEData *data, int pa_index)
1865 {
1866         ParticleSystem *psys= data->psys;
1867         ParticleEdit *edit= psys->edit;
1868         ParticleData *pa= &psys->particles[pa_index];
1869         ParticleEditKey *key;
1870         int k;
1871
1872         for(k=0,key=edit->keys[pa_index]; k<pa->totkey; k++,key++) {
1873                 if(key->flag & PEK_SELECT) continue;
1874
1875                 if(k==0) {
1876                         if((key+1)->flag&PEK_SELECT)
1877                                 key->flag |= PEK_TO_SELECT;
1878                 }
1879                 else if(k==pa->totkey-1) {
1880                         if((key-1)->flag&PEK_SELECT)
1881                                 key->flag |= PEK_TO_SELECT;
1882                 }
1883                 else {
1884                         if(((key-1)->flag | (key+1)->flag) & PEK_SELECT)
1885                                 key->flag |= PEK_TO_SELECT;
1886                 }
1887         }
1888
1889         for(k=0,key=edit->keys[pa_index]; k<pa->totkey; k++,key++) {
1890                 if(key->flag&PEK_TO_SELECT) {
1891                         key->flag &= ~PEK_TO_SELECT;
1892                         key->flag |= PEK_SELECT;
1893                 }
1894         }
1895 }
1896
1897 static int select_more_exec(bContext *C, wmOperator *op)
1898 {
1899         PEData data;
1900
1901         PE_set_data(C, &data);
1902         PE_foreach_particle(&data, select_more_keys);
1903         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob);
1904
1905         return OPERATOR_FINISHED;
1906 }
1907
1908 void PARTICLE_OT_select_more(wmOperatorType *ot)
1909 {
1910         /* identifiers */
1911         ot->name= "Select More";
1912         ot->idname= "PARTICLE_OT_select_more";
1913         
1914         /* api callbacks */
1915         ot->exec= select_more_exec;
1916         ot->poll= PE_poll;
1917
1918         /* flags */
1919         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1920 }
1921
1922 /************************ rekey operator ************************/
1923
1924 static void rekey_particle(PEData *data, int pa_index)
1925 {
1926         ParticleSystem *psys= data->psys;
1927         ParticleData *pa= &psys->particles[pa_index];
1928         ParticleEdit *edit= psys->edit;
1929         ParticleEditSettings *pset= PE_settings(data->scene);
1930         ParticleKey state;
1931         HairKey *key, *new_keys;
1932         ParticleEditKey *ekey;
1933         float dval, sta, end;
1934         int k;
1935
1936         pa->flag |= PARS_REKEY;
1937
1938         key= new_keys= MEM_callocN(pset->totrekey * sizeof(HairKey),"Hair re-key keys");
1939
1940         /* root and tip stay the same */
1941         VECCOPY(key->co, pa->hair->co);
1942         VECCOPY((key + pset->totrekey - 1)->co, (pa->hair + pa->totkey - 1)->co);
1943
1944         sta= key->time= pa->hair->time;
1945         end= (key + pset->totrekey - 1)->time= (pa->hair + pa->totkey - 1)->time;
1946         dval= (end - sta) / (float)(pset->totrekey - 1);
1947
1948         /* interpolate new keys from old ones */
1949         for(k=1,key++; k<pset->totrekey-1; k++,key++) {
1950                 state.time= (float)k / (float)(pset->totrekey-1);
1951                 psys_get_particle_on_path(data->scene, data->ob, psys, pa_index, &state, 0);
1952                 VECCOPY(key->co, state.co);
1953                 key->time= sta + k * dval;
1954         }
1955
1956         /* replace keys */
1957         if(pa->hair)
1958                 MEM_freeN(pa->hair);
1959         pa->hair= new_keys;
1960
1961         pa->totkey=pset->totrekey;
1962
1963         if(edit->keys[pa_index])
1964                 MEM_freeN(edit->keys[pa_index]);
1965         ekey= edit->keys[pa_index]= MEM_callocN(pa->totkey * sizeof(ParticleEditKey),"Hair re-key edit keys");
1966                 
1967         for(k=0, key=pa->hair; k<pa->totkey; k++, key++, ekey++) {
1968                 ekey->co= key->co;
1969                 ekey->time= &key->time;
1970         }
1971
1972         pa->flag &= ~PARS_REKEY;
1973         pa->flag |= PARS_EDIT_RECALC;
1974 }
1975
1976 static int rekey_exec(bContext *C, wmOperator *op)
1977 {
1978         PEData data;
1979         ParticleEditSettings *pset;
1980
1981         PE_set_data(C, &data);
1982
1983         pset= PE_settings(data.scene);
1984         pset->totrekey= RNA_int_get(op->ptr, "keys");
1985
1986         data.dval= 1.0f / (float)(pset->totrekey-1);
1987
1988         foreach_selected_particle(&data, rekey_particle);
1989         
1990         data.psys->edit->totkeys= psys_count_keys(data.psys);
1991         recalc_lengths(data.psys);
1992         
1993         PE_update_object(data.scene, data.ob, 1);
1994         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, data.ob);
1995
1996         return OPERATOR_FINISHED;
1997 }
1998
1999 void PARTICLE_OT_rekey(wmOperatorType *ot)
2000 {
2001         /* identifiers */
2002         ot->name= "Rekey";
2003         ot->idname= "PARTICLE_OT_rekey";
2004         
2005         /* api callbacks */
2006         ot->exec= rekey_exec;
2007         // XXX show buttons ot->invoke= rekey_invoke;
2008         ot->poll= PE_poll;
2009
2010         /* flags */
2011         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2012
2013         /* properties */
2014         RNA_def_int(ot->srna, "keys", 2, 2, INT_MAX, "Number of Keys", "", 2, 100);
2015 }
2016
2017 static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float path_time)
2018 {
2019         ParticleSystem *psys= PE_get_current(scene, ob);
2020         ParticleEdit *edit=0;
2021         ParticleData *pa;
2022         ParticleKey state;
2023         HairKey *new_keys, *key;
2024         ParticleEditKey *ekey;
2025         int k;
2026
2027         if(psys==0) return;
2028
2029         edit= psys->edit;
2030
2031         pa= &psys->particles[pa_index];
2032
2033         pa->flag |= PARS_REKEY;
2034
2035         key= new_keys= MEM_dupallocN(pa->hair);
2036         
2037         /* interpolate new keys from old ones (roots stay the same) */
2038         for(k=1, key++; k < pa->totkey; k++, key++) {
2039                 state.time= path_time * (float)k / (float)(pa->totkey-1);
2040                 psys_get_particle_on_path(scene, ob, psys, pa_index, &state, 0);
2041                 VECCOPY(key->co, state.co);
2042         }
2043
2044         /* replace hair keys */
2045         if(pa->hair)
2046                 MEM_freeN(pa->hair);
2047         pa->hair= new_keys;
2048
2049         /* update edit pointers */
2050         for(k=0, key=pa->hair, ekey=edit->keys[pa_index]; k<pa->totkey; k++, key++, ekey++) {
2051                 ekey->co= key->co;
2052                 ekey->time= &key->time;
2053         }
2054
2055         pa->flag &= ~PARS_REKEY;
2056 }
2057
2058 /************************* utilities **************************/
2059
2060 static int remove_tagged_particles(Scene *scene, Object *ob, ParticleSystem *psys)
2061 {
2062         ParticleEdit *edit= psys->edit;
2063         ParticleEditSettings *pset= PE_settings(scene);
2064         ParticleData *pa, *npa=0, *new_pars=0;
2065         ParticleEditKey **key, **nkey=0, **new_keys=0;
2066         ParticleSystemModifierData *psmd;
2067         int i, totpart, new_totpart= psys->totpart, removed= 0;
2068
2069         if(pset->flag & PE_X_MIRROR) {
2070                 /* mirror tags */
2071                 psmd= psys_get_modifier(ob, psys);
2072                 totpart= psys->totpart;
2073
2074                 LOOP_PARTICLES(i,pa)
2075                         if(pa->flag & PARS_TAG)
2076                                 PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
2077         }
2078
2079         for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++) {
2080                 if(pa->flag & PARS_TAG) {
2081                         new_totpart--;
2082                         removed++;
2083                 }
2084         }
2085
2086         if(new_totpart != psys->totpart) {
2087                 if(new_totpart) {
2088                         npa= new_pars= MEM_callocN(new_totpart * sizeof(ParticleData), "ParticleData array");
2089                         nkey= new_keys= MEM_callocN(new_totpart * sizeof(ParticleEditKey *), "ParticleEditKey array");
2090                 }
2091
2092                 pa= psys->particles;
2093                 key= edit->keys;
2094                 for(i=0; i<psys->totpart; i++, pa++, key++) {
2095                         if(pa->flag & PARS_TAG) {
2096                                 if(*key)
2097                                         MEM_freeN(*key);
2098                                 if(pa->hair)
2099                                         MEM_freeN(pa->hair);
2100                         }
2101                         else {
2102                                 memcpy(npa, pa, sizeof(ParticleData));
2103                                 memcpy(nkey, key, sizeof(ParticleEditKey*));
2104                                 npa++;
2105                                 nkey++;
2106                         }
2107                 }
2108
2109                 if(psys->particles) MEM_freeN(psys->particles);
2110                 psys->particles= new_pars;
2111
2112                 if(edit->keys) MEM_freeN(edit->keys);
2113                 edit->keys= new_keys;
2114
2115                 if(edit->mirror_cache) {
2116                         MEM_freeN(edit->mirror_cache);
2117                         edit->mirror_cache= NULL;
2118                 }
2119
2120                 psys->totpart= new_totpart;
2121
2122                 edit->totkeys= psys_count_keys(psys);
2123         }
2124
2125         return removed;
2126 }
2127
2128 static void remove_tagged_keys(Scene *scene, Object *ob, ParticleSystem *psys)
2129 {
2130         ParticleEdit *edit= psys->edit;
2131         ParticleEditSettings *pset= PE_settings(scene);
2132         ParticleData *pa;
2133         HairKey *key, *nkey, *new_keys=0;
2134         ParticleEditKey *ekey;
2135         ParticleSystemModifierData *psmd;
2136         int i, k, totpart= psys->totpart;
2137         short new_totkey;
2138
2139         if(pset->flag & PE_X_MIRROR) {
2140                 /* mirror key tags */
2141                 psmd= psys_get_modifier(ob, psys);
2142
2143                 LOOP_PARTICLES(i,pa) {
2144                         LOOP_KEYS(k,ekey) {
2145                                 if(ekey->flag & PEK_TAG) {
2146                                         PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
2147                                         break;
2148                                 }
2149                         }
2150                 }
2151         }
2152
2153         LOOP_PARTICLES(i,pa) {
2154                 new_totkey= pa->totkey;
2155                 LOOP_KEYS(k,ekey) {
2156                         if(ekey->flag & PEK_TAG)
2157                                 new_totkey--;
2158                 }
2159                 /* we can't have elements with less than two keys*/
2160                 if(new_totkey < 2)
2161                         pa->flag |= PARS_TAG;
2162         }
2163         remove_tagged_particles(scene, ob, psys);
2164
2165         totpart= psys->totpart;
2166
2167         LOOP_PARTICLES(i,pa) {
2168                 new_totkey= pa->totkey;
2169                 LOOP_KEYS(k,ekey) {
2170                         if(ekey->flag & PEK_TAG)
2171                                 new_totkey--;
2172                 }
2173                 if(new_totkey != pa->totkey) {
2174                         key= pa->hair;
2175                         nkey= new_keys= MEM_callocN(new_totkey*sizeof(HairKey), "HairKeys");
2176
2177                         for(k=0, ekey=edit->keys[i]; k<new_totkey; k++, key++, nkey++, ekey++) {
2178                                 while(ekey->flag & PEK_TAG && key < pa->hair + pa->totkey) {
2179                                         key++;
2180                                         ekey++;
2181                                 }
2182
2183                                 if(key < pa->hair + pa->totkey) {
2184                                         VECCOPY(nkey->co, key->co);
2185                                         nkey->time= key->time;
2186                                         nkey->weight= key->weight;
2187                                 }
2188                         }
2189                         if(pa->hair)
2190                                 MEM_freeN(pa->hair);
2191                         
2192                         pa->hair= new_keys;
2193
2194                         pa->totkey=new_totkey;
2195
2196                         if(edit->keys[i])
2197                                 MEM_freeN(edit->keys[i]);
2198                         ekey= edit->keys[i]= MEM_callocN(new_totkey*sizeof(ParticleEditKey), "particle edit keys");
2199
2200                         for(k=0, key=pa->hair; k<pa->totkey; k++, key++, ekey++) {
2201                                 ekey->co= key->co;
2202                                 ekey->time= &key->time;
2203                         }
2204                 }
2205         }
2206
2207         edit->totkeys= psys_count_keys(psys);
2208 }
2209
2210 /************************ subdivide opertor *********************/
2211
2212 /* works like normal edit mode subdivide, inserts keys between neighbouring selected keys */
2213 static void subdivide_particle(PEData *data, int pa_index)
2214 {
2215         ParticleSystem *psys= data->psys;
2216         ParticleEdit *edit= psys->edit;
2217         ParticleData *pa= &psys->particles[pa_index];
2218         
2219         ParticleKey state;
2220         HairKey *key, *nkey, *new_keys;
2221         ParticleEditKey *ekey, *nekey, *new_ekeys;
2222
2223         int k;
2224         short totnewkey=0;
2225         float endtime;
2226
2227         for(k=0, ekey=edit->keys[pa_index]; k<pa->totkey-1; k++,ekey++) {
2228                 if(ekey->flag&PEK_SELECT && (ekey+1)->flag&PEK_SELECT)
2229                         totnewkey++;
2230         }
2231
2232         if(totnewkey==0) return;
2233
2234         pa->flag |= PARS_REKEY;
2235
2236         nkey= new_keys= MEM_callocN((pa->totkey+totnewkey)*(sizeof(HairKey)),"Hair subdivide keys");
2237         nekey= new_ekeys= MEM_callocN((pa->totkey+totnewkey)*(sizeof(ParticleEditKey)),"Hair subdivide edit keys");
2238         endtime= pa->hair[pa->totkey-1].time;
2239
2240         for(k=0, key=pa->hair, ekey=edit->keys[pa_index]; k<pa->totkey-1; k++, key++, ekey++) {
2241
2242                 memcpy(nkey,key,sizeof(HairKey));
2243                 memcpy(nekey,ekey,sizeof(ParticleEditKey));
2244
2245                 nekey->co= nkey->co;
2246                 nekey->time= &nkey->time;
2247
2248                 nkey++;
2249                 nekey++;
2250
2251                 if(ekey->flag & PEK_SELECT && (ekey+1)->flag & PEK_SELECT) {
2252                         nkey->time= (key->time + (key+1)->time)*0.5f;
2253                         state.time= (endtime != 0.0f)? nkey->time/endtime: 0.0f;
2254                         psys_get_particle_on_path(data->scene, data->ob, psys, pa_index, &state, 0);
2255                         VECCOPY(nkey->co, state.co);
2256
2257                         nekey->co= nkey->co;
2258                         nekey->time= &nkey->time;
2259                         nekey->flag |= PEK_SELECT;
2260
2261                         nekey++;
2262                         nkey++;
2263                 }
2264         }
2265         /*tip still not copied*/
2266         memcpy(nkey,key,sizeof(HairKey));
2267         memcpy(nekey,ekey,sizeof(ParticleEditKey));
2268
2269         nekey->co= nkey->co;
2270         nekey->time= &nkey->time;
2271
2272         if(pa->hair)
2273                 MEM_freeN(pa->hair);
2274         pa->hair= new_keys;
2275
2276         if(edit->keys[pa_index])
2277                 MEM_freeN(edit->keys[pa_index]);
2278
2279         edit->keys[pa_index]= new_ekeys;
2280
2281         pa->totkey += totnewkey;
2282         pa->flag |= PARS_EDIT_RECALC;
2283         pa->flag &= ~PARS_REKEY;
2284 }
2285
2286 static int subdivide_exec(bContext *C, wmOperator *op)
2287 {
2288         PEData data;
2289
2290         PE_set_data(C, &data);
2291         PE_foreach_particle(&data, subdivide_particle);
2292         
2293         data.psys->edit->totkeys= psys_count_keys(data.psys);
2294         
2295         recalc_lengths(data.psys);
2296         PE_recalc_world_cos(data.ob, data.psys);
2297
2298         PE_update_object(data.scene, data.ob, 1);
2299         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, data.ob);
2300
2301         return OPERATOR_FINISHED;
2302 }
2303
2304 void PARTICLE_OT_subdivide(wmOperatorType *ot)
2305 {
2306         /* identifiers */
2307         ot->name= "Subdivide";
2308         ot->idname= "PARTICLE_OT_subdivide";
2309         
2310         /* api callbacks */
2311         ot->exec= subdivide_exec;
2312         ot->poll= PE_poll;
2313
2314         /* flags */
2315         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2316 }
2317
2318 /************************ remove doubles opertor *********************/
2319
2320 static int remove_doubles_exec(bContext *C, wmOperator *op)
2321 {
2322         Scene *scene= CTX_data_scene(C);
2323         Object *ob= CTX_data_active_object(C);
2324         ParticleSystem *psys= PE_get_current(scene, ob);
2325         ParticleEditSettings *pset=PE_settings(scene);
2326         ParticleData *pa;
2327         ParticleEdit *edit;
2328         ParticleSystemModifierData *psmd;
2329         KDTree *tree;
2330         KDTreeNearest nearest[10];
2331         float mat[4][4], co[3], threshold= RNA_float_get(op->ptr, "threshold");
2332         int i, n, totn, removed, totpart, flag, totremoved;
2333
2334         edit= psys->edit;
2335         psmd= psys_get_modifier(ob, psys);
2336         totremoved= 0;
2337
2338         do {
2339                 removed= 0;
2340
2341                 totpart= psys->totpart;
2342                 tree=BLI_kdtree_new(totpart);
2343                         
2344                 /* insert particles into kd tree */
2345                 LOOP_PARTICLES(i,pa) {
2346                         if(particle_is_selected(psys, pa)) {
2347                                 psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, mat);
2348                                 VECCOPY(co, pa->hair[0].co);
2349                                 Mat4MulVecfl(mat, co);
2350                                 BLI_kdtree_insert(tree, i, co, NULL);
2351                         }
2352                 }
2353
2354                 BLI_kdtree_balance(tree);
2355
2356                 /* tag particles to be removed */
2357                 LOOP_PARTICLES(i,pa) {
2358                         if(particle_is_selected(psys, pa)) {
2359                                 psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, mat);
2360                                 VECCOPY(co, pa->hair[0].co);
2361                                 Mat4MulVecfl(mat, co);
2362
2363                                 totn= BLI_kdtree_find_n_nearest(tree,10,co,NULL,nearest);
2364
2365                                 for(n=0; n<totn; n++) {
2366                                         /* this needs a custom threshold still */
2367                                         if(nearest[n].index > i && nearest[n].dist < threshold) {
2368                                                 if(!(pa->flag & PARS_TAG)) {
2369                                                         pa->flag |= PARS_TAG;
2370                                                         removed++;
2371                                                 }
2372                                         }
2373                                 }
2374                         }
2375                 }
2376
2377                 BLI_kdtree_free(tree);
2378
2379                 /* remove tagged particles - don't do mirror here! */
2380                 flag= pset->flag;
2381                 pset->flag &= ~PE_X_MIRROR;
2382                 remove_tagged_particles(scene, ob, psys);
2383                 pset->flag= flag;
2384                 totremoved += removed;
2385         } while(removed);
2386
2387         if(totremoved == 0)
2388                 return OPERATOR_CANCELLED;
2389
2390         BKE_reportf(op->reports, RPT_INFO, "Remove %d double particles.", totremoved);
2391
2392         PE_recalc_world_cos(ob, psys);
2393         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
2394         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
2395
2396         return OPERATOR_FINISHED;
2397 }
2398
2399 void PARTICLE_OT_remove_doubles(wmOperatorType *ot)
2400 {
2401         /* identifiers */
2402         ot->name= "Remove Doubles";
2403         ot->idname= "PARTICLE_OT_remove_doubles";
2404         
2405         /* api callbacks */
2406         ot->exec= remove_doubles_exec;
2407         ot->poll= PE_poll;
2408
2409         /* flags */
2410         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2411
2412         /* properties */
2413         RNA_def_float(ot->srna, "threshold", 0.0002f, 0.0f, FLT_MAX, "Threshold", "Threshold distance withing which particles are removed", 0.00001f, 0.1f);
2414 }
2415
2416 /********************* radial control operator *********************/
2417
2418 /* XXX static */
2419 void PE_radialcontrol_callback(const int mode, const int val)
2420 {
2421         ParticleEditSettings *pset= NULL; // XXX PE_settings(scene);
2422
2423         if(pset->brushtype>=0) {
2424                 ParticleBrushData *brush= &pset->brush[pset->brushtype];
2425
2426                 if(mode == RADIALCONTROL_SIZE)
2427                         brush->size= val;
2428                 else if(mode == RADIALCONTROL_STRENGTH)
2429                         brush->strength= val;
2430         }
2431
2432         (*PE_radialcontrol())= NULL;
2433 }
2434
2435 struct RadialControl **PE_radialcontrol(void)
2436 {
2437         static struct RadialControl *rc= NULL;
2438         return &rc;
2439 }
2440
2441 void PE_radialcontrol_start(const int mode)
2442 {
2443         ParticleEditSettings *pset= NULL; // XXX PE_settings(scene);
2444         int orig= 1;
2445
2446         if(pset->brushtype>=0) {
2447                 ParticleBrushData *brush= &pset->brush[pset->brushtype];
2448                 
2449                 if(mode == RADIALCONTROL_SIZE)
2450                         orig= brush->size;
2451                 else if(mode == RADIALCONTROL_STRENGTH)
2452                         orig= brush->strength;
2453                 
2454 //              if(mode != RADIALCONTROL_NONE)
2455 //                      (*PE_radialcontrol())= radialcontrol_start(mode, PE_radialcontrol_callback, orig, 100, 0);
2456         }
2457 }
2458
2459 /*************************** delete operator **************************/
2460
2461 enum { DEL_PARTICLE, DEL_KEY };
2462
2463 static EnumPropertyItem delete_type_items[]= {
2464         {DEL_PARTICLE, "PARTICLE", "Particle", ""},
2465         {DEL_KEY, "KEY", "Key", ""},
2466         {0, NULL, NULL}};
2467
2468 static void set_delete_particle(PEData *data, int pa_index)
2469 {
2470         ParticleSystem *psys= data->psys;
2471
2472         psys->particles[pa_index].flag |= PARS_TAG;
2473 }
2474
2475 static void set_delete_particle_key(PEData *data, int pa_index, int key_index)
2476 {
2477         ParticleSystem *psys= data->psys;
2478
2479         psys->edit->keys[pa_index][key_index].flag |= PEK_TAG;
2480 }
2481
2482 static int delete_exec(bContext *C, wmOperator *op)
2483 {
2484         PEData data;
2485         int type= RNA_enum_get(op->ptr, "type");
2486
2487         PE_set_data(C, &data);
2488
2489         if(type == DEL_KEY) {
2490                 foreach_selected_key(&data, set_delete_particle_key);
2491                 remove_tagged_keys(data.scene, data.ob, data.psys);
2492                 recalc_lengths(data.psys);
2493         }
2494         else if(type == DEL_PARTICLE) {
2495                 foreach_selected_particle(&data, set_delete_particle);
2496                 remove_tagged_particles(data.scene, data.ob, data.psys);
2497                 recalc_lengths(data.psys);
2498         }
2499
2500         DAG_object_flush_update(data.scene, data.ob, OB_RECALC_DATA);
2501         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, data.ob);
2502
2503         return OPERATOR_FINISHED;
2504 }
2505
2506 void PARTICLE_OT_delete(wmOperatorType *ot)
2507 {
2508         /* identifiers */
2509         ot->name= "Delete";
2510         ot->idname= "PARTICLE_OT_delete";
2511         
2512         /* api callbacks */
2513         ot->exec= delete_exec;
2514         ot->invoke= WM_menu_invoke;
2515         ot->poll= PE_poll;
2516
2517         /* flags */
2518         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2519
2520         /* properties */
2521         RNA_def_enum(ot->srna, "type", delete_type_items, DEL_PARTICLE, "Type", "Delete a full particle or only keys.");
2522 }
2523
2524 /*************************** mirror operator **************************/
2525
2526 static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
2527 {
2528         Mesh *me= (Mesh*)(ob->data);
2529         ParticleSystemModifierData *psmd;
2530         ParticleSystem *psys= PE_get_current(scene, ob);
2531         ParticleEdit *edit;
2532         ParticleData *pa, *newpa, *new_pars;
2533         ParticleEditKey *ekey, **newkey, **key, **new_keys;
2534         HairKey *hkey;
2535         int *mirrorfaces;
2536         int i, k, rotation, totpart, newtotpart;
2537
2538         edit= psys->edit;
2539         psmd= psys_get_modifier(ob, psys);
2540
2541         mirrorfaces= mesh_get_x_mirror_faces(ob);
2542
2543         if(!edit->mirror_cache)
2544                 PE_update_mirror_cache(ob, psys);
2545
2546         totpart= psys->totpart;
2547         newtotpart= psys->totpart;
2548         LOOP_PARTICLES(i,pa) {
2549                 if(pa->flag & PARS_HIDE) continue;
2550
2551                 if(!tagged) {
2552                         if(particle_is_selected(psys, pa)) {
2553                                 if(edit->mirror_cache[i] != -1) {
2554                                         /* already has a mirror, don't need to duplicate */
2555                                         PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
2556                                         continue;
2557                                 }
2558                                 else
2559                                         pa->flag |= PARS_TAG;
2560                         }
2561                 }
2562
2563                 if((pa->flag & PARS_TAG) && mirrorfaces[pa->num*2] != -1)
2564                         newtotpart++;
2565         }
2566
2567         if(newtotpart != psys->totpart) {
2568                 /* allocate new arrays and copy existing */
2569                 new_pars= MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new");
2570                 new_keys= MEM_callocN(newtotpart*sizeof(ParticleEditKey*), "ParticleEditKey new");
2571
2572                 memcpy(new_pars, psys->particles, totpart*sizeof(ParticleData));
2573                 memcpy(new_keys, edit->keys, totpart*sizeof(ParticleEditKey*));
2574
2575                 if(psys->particles) MEM_freeN(psys->particles);
2576                 psys->particles= new_pars;
2577
2578                 if(edit->keys) MEM_freeN(edit->keys);
2579                 edit->keys= new_keys;
2580
2581                 if(edit->mirror_cache) {
2582                         MEM_freeN(edit->mirror_cache);
2583                         edit->mirror_cache= NULL;
2584                 }
2585
2586                 psys->totpart= newtotpart;
2587                         
2588                 /* create new elements */
2589                 pa= psys->particles;
2590                 newpa= psys->particles + totpart;
2591                 key= edit->keys;
2592                 newkey= edit->keys + totpart;
2593
2594                 for(i=0; i<totpart; i++, pa++, key++) {
2595                         if(pa->flag & PARS_HIDE) continue;
2596
2597                         if(!(pa->flag & PARS_TAG) || mirrorfaces[pa->num*2] == -1)
2598                                 continue;
2599
2600                         /* duplicate */
2601                         *newpa= *pa;
2602                         if(pa->hair) newpa->hair= MEM_dupallocN(pa->hair);
2603                         if(pa->keys) newpa->keys= MEM_dupallocN(pa->keys);
2604                         if(*key) *newkey= MEM_dupallocN(*key);
2605
2606                         /* rotate weights according to vertex index rotation */
2607                         rotation= mirrorfaces[pa->num*2+1];
2608                         newpa->fuv[0]= pa->fuv[2];
2609                         newpa->fuv[1]= pa->fuv[1];
2610                         newpa->fuv[2]= pa->fuv[0];
2611                         newpa->fuv[3]= pa->fuv[3];
2612                         while(rotation-- > 0)
2613                                 if(me->mface[pa->num].v4)
2614                                         SHIFT4(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2], newpa->fuv[3])
2615                                 else
2616                                         SHIFT3(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2])
2617
2618                         /* assign face inddex */
2619                         newpa->num= mirrorfaces[pa->num*2];
2620                         newpa->num_dmcache= psys_particle_dm_face_lookup(ob,psmd->dm,newpa->num,newpa->fuv, NULL);
2621
2622                         /* update edit key pointers */
2623                         ekey= *newkey;
2624                         for(k=0, hkey=newpa->hair; k<newpa->totkey; k++, hkey++, ekey++) {
2625                                 ekey->co= hkey->co;
2626                                 ekey->time= &hkey->time;
2627                         }
2628
2629                         /* map key positions as mirror over x axis */
2630                         PE_mirror_particle(ob, psmd->dm, psys, pa, newpa);
2631
2632                         newpa++;
2633                         newkey++;
2634                 }
2635
2636                 edit->totkeys= psys_count_keys(psys);
2637         }
2638
2639         for(pa=psys->particles, i=0; i<psys->totpart; i++, pa++)
2640                 pa->flag &= ~PARS_TAG;
2641
2642         MEM_freeN(mirrorfaces);
2643 }
2644
2645 static int mirror_exec(bContext *C, wmOperator *op)
2646 {
2647         Scene *scene= CTX_data_scene(C);
2648         Object *ob= CTX_data_active_object(C);
2649         ParticleSystem *psys= PE_get_current(scene, ob);
2650         
2651         PE_mirror_x(scene, ob, 0);
2652
2653         PE_recalc_world_cos(ob, psys);
2654         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
2655         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
2656
2657         return OPERATOR_FINISHED;
2658 }
2659
2660 void PARTICLE_OT_mirror(wmOperatorType *ot)
2661 {
2662         /* identifiers */
2663         ot->name= "Mirror";
2664         ot->idname= "PARTICLE_OT_mirror";
2665         
2666         /* api callbacks */
2667         ot->exec= mirror_exec;
2668         ot->poll= PE_poll;
2669
2670         /* flags */
2671         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2672 }
2673
2674 /*********************** set brush operator **********************/
2675
2676 static EnumPropertyItem brush_type_items[]= {
2677         {PE_BRUSH_NONE, "NONE", "None", ""},
2678         {PE_BRUSH_COMB, "COMB", "Comb", ""},
2679         {PE_BRUSH_SMOOTH, "SMOOTH", "Smooth", ""},
2680         {PE_BRUSH_WEIGHT, "WEIGHT", "Weight", ""},
2681         {PE_BRUSH_ADD, "ADD", "Add", ""},
2682         {PE_BRUSH_LENGTH, "LENGTH", "Length", ""},
2683         {PE_BRUSH_PUFF, "PUFF", "Puff", ""},
2684         {PE_BRUSH_CUT, "CUT", "Cut", ""},
2685         {0, NULL, NULL, NULL}
2686 };
2687
2688 static int set_brush_exec(bContext *C, wmOperator *op)
2689 {
2690         Scene *scene= CTX_data_scene(C);
2691         ParticleEditSettings *pset= PE_settings(scene);
2692
2693         pset->brushtype= RNA_enum_get(op->ptr, "type");
2694
2695         return OPERATOR_FINISHED;
2696 }
2697
2698 void PARTICLE_OT_set_brush(wmOperatorType *ot)
2699 {
2700         /* identifiers */
2701         ot->name= "Set Brush";
2702         ot->idname= "PARTICLE_OT_set_brush";
2703         
2704         /* api callbacks */
2705         ot->exec= set_brush_exec;
2706         ot->invoke= WM_menu_invoke;
2707         ot->poll= PE_poll;
2708
2709         /* properties */
2710         RNA_def_enum(ot->srna, "type", brush_type_items, PE_BRUSH_NONE, "Type", "Brush type to select for editing.");
2711 }
2712
2713 /************************* brush edit callbacks ********************/
2714
2715 static void brush_comb(PEData *data, float mat[][4], float imat[][4], int pa_index, int key_index)
2716 {
2717         ParticleSystem *psys= data->psys;
2718         ParticleData *pa= &psys->particles[pa_index];
2719         ParticleEditSettings *pset= PE_settings(data->scene);
2720         HairKey *key= pa->hair + key_index;
2721         float cvec[3], fac;
2722
2723         if(pset->flag & PE_LOCK_FIRST && key_index == 0) return;
2724
2725         fac= (float)pow((double)(1.0f - data->dist / data->rad), (double)data->combfac);
2726
2727         VECCOPY(cvec,data->dvec);
2728         Mat4Mul3Vecfl(imat,cvec);
2729         VecMulf(cvec, fac);
2730         VECADD(key->co, key->co, cvec);
2731
2732         pa->flag |= PARS_EDIT_RECALC;
2733 }
2734
2735 static void brush_cut(PEData *data, int pa_index)
2736 {
2737         ParticleSystem *psys= data->psys;
2738         ARegion *ar= data->vc.ar;
2739         Object *ob= data->ob;
2740         ParticleData *pa= &psys->particles[pa_index];
2741         ParticleCacheKey *key= psys->pathcache[pa_index];
2742         float rad2, cut_time= 1.0;
2743         float x0, x1, v0, v1, o0, o1, xo0, xo1, d, dv;
2744         int k, cut, keys= (int)pow(2.0, (double)psys->part->draw_step);
2745         short vertco[2];
2746
2747         /* blunt scissors */
2748         if(BLI_frand() > data->cutfac) return;
2749
2750         rad2= data->rad * data->rad;
2751
2752         cut=0;
2753
2754         project_short_noclip(ar, key->co, vertco);
2755         x0= (float)vertco[0];
2756         x1= (float)vertco[1];
2757
2758         o0= (float)data->mval[0];
2759         o1= (float)data->mval[1];
2760         
2761         xo0= x0 - o0;
2762         xo1= x1 - o1;
2763
2764         /* check if root is inside circle */
2765         if(xo0*xo0 + xo1*xo1 < rad2 && key_test_depth(data, key->co)) {
2766                 cut_time= -1.0f;
2767                 cut= 1;
2768         }
2769         else {
2770                 /* calculate path time closest to root that was inside the circle */
2771                 for(k=1, key++; k<=keys; k++, key++) {
2772                         project_short_noclip(ar, key->co, vertco);
2773
2774                         if(key_test_depth(data, key->co) == 0) {
2775                                 x0= (float)vertco[0];
2776                                 x1= (float)vertco[1];
2777
2778                                 xo0= x0 - o0;
2779                                 xo1= x1 - o1;
2780                                 continue;
2781                         }
2782
2783                         v0= (float)vertco[0] - x0;
2784                         v1= (float)vertco[1] - x1;
2785
2786                         dv= v0*v0 + v1*v1;
2787
2788                         d= (v0*xo1 - v1*xo0);
2789                         
2790                         d= dv * rad2 - d*d;
2791
2792                         if(d > 0.0f) {
2793                                 d= sqrt(d);
2794
2795                                 cut_time= -(v0*xo0 + v1*xo1 + d);
2796
2797                                 if(cut_time > 0.0f) {
2798                                         cut_time /= dv;
2799
2800                                         if(cut_time < 1.0f) {
2801                                                 cut_time += (float)(k-1);
2802                                                 cut_time /= (float)keys;
2803                                                 cut= 1;
2804                                                 break;
2805                                         }
2806                                 }
2807                         }
2808
2809                         x0= (float)vertco[0];
2810                         x1= (float)vertco[1];
2811
2812                         xo0= x0 - o0;
2813                         xo1= x1 - o1;
2814                 }
2815         }
2816
2817         if(cut) {
2818                 if(cut_time < 0.0f) {
2819                         pa->flag |= PARS_TAG;
2820                 }
2821                 else {
2822                         rekey_particle_to_time(data->scene, ob, pa_index, cut_time);
2823                         pa->flag |= PARS_EDIT_RECALC;
2824                 }
2825         }
2826 }
2827
2828 static void brush_length(PEData *data, int pa_index)
2829 {
2830         ParticleSystem *psys= data->psys;
2831         ParticleData *pa= &psys->particles[pa_index];
2832         HairKey *key;
2833         float dvec[3],pvec[3];
2834         int k;
2835
2836         key= pa->hair;
2837         VECCOPY(pvec,key->co);
2838
2839         for(k=1, key++; k<pa->totkey; k++,key++) {
2840                 VECSUB(dvec,key->co,pvec);
2841                 VECCOPY(pvec,key->co);
2842                 VecMulf(dvec,data->growfac);
2843                 VECADD(key->co,(key-1)->co,dvec);
2844         }
2845
2846         pa->flag |= PARS_EDIT_RECALC;
2847 }
2848
2849 static void brush_puff(PEData *data, int pa_index)
2850 {
2851         ParticleSystem *psys= data->psys;
2852         ParticleData *pa= &psys->particles[pa_index];
2853         ParticleEdit *edit= psys->edit;
2854         HairKey *key;
2855         float mat[4][4], imat[4][4];
2856         float lastco[3], rootco[3], co[3], nor[3], kco[3], dco[3], fac, length;
2857         int k;
2858
2859         psys_mat_hair_to_global(data->ob, data->dm, psys->part->from, pa, mat);
2860         Mat4Invert(imat,mat);
2861
2862         /* find root coordinate and normal on emitter */
2863         key= pa->hair;
2864         VECCOPY(co, key->co);
2865         Mat4MulVecfl(mat, co);
2866
2867         pa_index= BLI_kdtree_find_nearest(edit->emitter_field, co, NULL, NULL);
2868         if(pa_index == -1) return;
2869
2870         VECCOPY(rootco, co);
2871         VecCopyf(nor, &psys->edit->emitter_cosnos[pa_index*6+3]);
2872         Normalize(nor);
2873         length= 0.0f;
2874
2875         fac= (float)pow((double)(1.0f - data->dist / data->rad), (double)data->pufffac);
2876         fac *= 0.025f;
2877         if(data->invert)
2878                 fac= -fac;
2879
2880         for(k=1, key++; k<pa->totkey; k++, key++) {
2881                 /* compute position as if hair was standing up straight */
2882                 VECCOPY(lastco, co);
2883                 VECCOPY(co, key->co);
2884                 Mat4MulVecfl(mat, co);
2885                 length += VecLenf(lastco, co);
2886
2887                 VECADDFAC(kco, rootco, nor, length);
2888
2889                 /* blend between the current and straight position */
2890                 VECSUB(dco, kco, co);
2891                 VECADDFAC(co, co, dco, fac);
2892
2893                 VECCOPY(key->co, co);
2894                 Mat4MulVecfl(imat, key->co);
2895         }
2896
2897         pa->flag |= PARS_EDIT_RECALC;
2898 }
2899
2900 static void brush_smooth_get(PEData *data, float mat[][4], float imat[][4], int pa_index, int key_index)
2901 {
2902         ParticleSystem *psys= data->psys;
2903         ParticleData *pa= &psys->particles[pa_index];
2904         HairKey *key= pa->hair + key_index;
2905         
2906         if(key_index) {
2907                 float dvec[3];
2908
2909                 VecSubf(dvec,key->co,(key-1)->co);
2910                 Mat4Mul3Vecfl(mat,dvec);
2911                 VECADD(data->vec,data->vec,dvec);
2912                 data->tot++;
2913         }
2914 }
2915
2916 static void brush_smooth_do(PEData *data, float mat[][4], float imat[][4], int pa_index, int key_index)
2917 {
2918         ParticleSystem *psys= data->psys;
2919         ParticleData *pa= &psys->particles[pa_index];
2920         HairKey *key= pa->hair + key_index;
2921         float vec[3], dvec[3];
2922         
2923         if(key_index) {
2924                 VECCOPY(vec,data->vec);
2925                 Mat4Mul3Vecfl(imat,vec);
2926
2927                 VecSubf(dvec,key->co,(key-1)->co);
2928
2929                 VECSUB(dvec,vec,dvec);
2930                 VecMulf(dvec,data->smoothfac);
2931                 
2932                 VECADD(key->co,key->co,dvec);
2933         }
2934
2935         pa->flag |= PARS_EDIT_RECALC;
2936 }
2937
2938 static void brush_add(PEData *data, short number)
2939 {
2940         Scene *scene= data->scene;
2941         Object *ob= data->ob;
2942         ParticleSystem *psys= data->psys;
2943         ParticleData *add_pars= MEM_callocN(number*sizeof(ParticleData),"ParticleData add");
2944         ParticleSystemModifierData *psmd= psys_get_modifier(ob,psys);
2945         ParticleEditSettings *pset= PE_settings(scene);
2946         ParticleEdit *edit= psys->edit;
2947         int i, k, n= 0, totpart= psys->totpart;
2948         short mco[2];
2949         short dmx= 0, dmy= 0;
2950         float co1[3], co2[3], min_d, imat[4][4];
2951         float framestep, timestep= psys_get_timestep(psys->part);
2952         short size= pset->brush[PE_BRUSH_ADD].size;
2953         short size2= size*size;
2954         DerivedMesh *dm=0;
2955         Mat4Invert(imat,ob->obmat);
2956
2957         BLI_srandom(psys->seed+data->mval[0]+data->mval[1]);
2958         
2959         /* painting onto the deformed mesh, could be an option? */
2960         if(psmd->dm->deformedOnly)
2961                 dm= psmd->dm;
2962         else
2963                 dm= mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
2964
2965         for(i=0; i<number; i++) {
2966                 if(number>1) {
2967                         dmx=dmy=size;
2968                         while(dmx*dmx+dmy*dmy>size2) {
2969                                 dmx=(short)((2.0f*BLI_frand()-1.0f)*size);
2970                                 dmy=(short)((2.0f*BLI_frand()-1.0f)*size);
2971                         }
2972                 }
2973
2974                 mco[0]= data->mval[0] + dmx;
2975                 mco[1]= data->mval[1] + dmy;
2976                 viewline(data->vc.ar, data->vc.v3d, mco, co1, co2);
2977
2978                 Mat4MulVecfl(imat,co1);
2979                 Mat4MulVecfl(imat,co2);
2980                 min_d=2.0;
2981                 
2982                 /* warning, returns the derived mesh face */
2983                 if(psys_intersect_dm(scene, ob,dm,0,co1,co2,&min_d,&add_pars[n].num,add_pars[n].fuv,0,0,0,0)) {
2984                         add_pars[n].num_dmcache= psys_particle_dm_face_lookup(ob,psmd->dm,add_pars[n].num,add_pars[n].fuv,NULL);
2985                         n++;
2986                 }
2987         }
2988         if(n) {
2989                 int newtotpart=totpart+n;
2990                 float hairmat[4][4], cur_co[3];
2991                 KDTree *tree=0;
2992                 ParticleData *pa, *new_pars= MEM_callocN(newtotpart*sizeof(ParticleData),"ParticleData new");
2993                 ParticleEditKey *ekey, **key, **new_keys= MEM_callocN(newtotpart*sizeof(ParticleEditKey *),"ParticleEditKey array new");
2994                 HairKey *hkey;
2995
2996                 /* save existing elements */
2997                 memcpy(new_pars, psys->particles, totpart * sizeof(ParticleData));
2998                 memcpy(new_keys, edit->keys, totpart * sizeof(ParticleEditKey*));
2999
3000                 /* change old arrays to new ones */
3001                 if(psys->particles) MEM_freeN(psys->particles);
3002                 psys->particles= new_pars;
3003
3004                 if(edit->keys) MEM_freeN(edit->keys);
3005                 edit->keys= new_keys;
3006
3007                 if(edit->mirror_cache) {
3008                         MEM_freeN(edit->mirror_cache);
3009                         edit->mirror_cache= NULL;
3010                 }
3011
3012                 /* create tree for interpolation */
3013                 if(pset->flag & PE_INTERPOLATE_ADDED && psys->totpart) {
3014                         tree=BLI_kdtree_new(psys->totpart);
3015                         
3016                         for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
3017                                 psys_particle_on_dm(psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,cur_co,0,0,0,0,0);
3018                                 BLI_kdtree_insert(tree, i, cur_co, NULL);
3019                         }
3020
3021                         BLI_kdtree_balance(tree);
3022                 }
3023
3024                 psys->totpart= newtotpart;
3025
3026                 /* create new elements */
3027                 pa= psys->particles + totpart;
3028                 key= edit->keys + totpart;
3029
3030                 for(i=totpart; i<newtotpart; i++, pa++, key++) {
3031                         memcpy(pa, add_pars + i - totpart, sizeof(ParticleData));
3032                         pa->hair= MEM_callocN(pset->totaddkey * sizeof(HairKey), "BakeKey key add");
3033                         ekey= *key= MEM_callocN(pset->totaddkey * sizeof(ParticleEditKey), "ParticleEditKey add");
3034                         pa->totkey= pset->totaddkey;
3035
3036                         for(k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, ekey++) {
3037                                 ekey->co= hkey->co;
3038                                 ekey->time= &hkey->time;
3039                         }
3040                         
3041                         pa->size= 1.0f;
3042                         initialize_particle(pa,i,ob,psys,psmd);
3043                         reset_particle(scene, pa,psys,psmd,ob,0.0,1.0,0,0,0);
3044                         pa->flag |= PARS_EDIT_RECALC;
3045                         if(pset->flag & PE_X_MIRROR)
3046                                 pa->flag |= PARS_TAG; /* signal for duplicate */
3047                         
3048                         framestep= pa->lifetime/(float)(pset->totaddkey-1);
3049
3050                         if(tree) {
3051                                 HairKey *hkey;
3052                                 ParticleKey key[3];
3053                                 KDTreeNearest ptn[3];
3054                                 int w, maxw;
3055                                 float maxd, mind, dd, totw=0.0, weight[3];
3056
3057                                 psys_particle_on_dm(psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,0,0);
3058                                 maxw= BLI_kdtree_find_n_nearest(tree,3,co1,NULL,ptn);
3059
3060                                 maxd= ptn[maxw-1].dist;
3061                                 mind= ptn[0].dist;
3062                                 dd= maxd - mind;
3063                                 
3064                                 for(w=0; w<maxw; w++) {
3065                                         weight[w]= (float)pow(2.0, (double)(-6.0f * ptn[w].dist / maxd));
3066                                         totw += weight[w];
3067                                 }
3068                                 for(;w<3; w++) {
3069                                         weight[w]= 0.0f;
3070                                 }
3071
3072                                 for(w=0; w<maxw; w++)
3073                                         weight[w] /= totw;
3074
3075                                 for(k=0; k<pset->totaddkey; k++) {
3076                                         hkey= pa->hair + k;
3077                                         hkey->time= pa->time + k * framestep;
3078
3079                                         key[0].time= hkey->time/ 100.0f;
3080                                         psys_get_particle_on_path(scene, ob, psys, ptn[0].index, key, 0);
3081                                         VecMulf(key[0].co, weight[0]);
3082                                         
3083                                         if(maxw>1) {
3084                                                 key[1].time= key[0].time;
3085                                                 psys_get_particle_on_path(scene, ob, psys, ptn[1].index, key + 1, 0);
3086                                                 VecMulf(key[1].co, weight[1]);
3087                                                 VECADD(key[0].co, key[0].co, key[1].co);
3088
3089                                                 if(maxw>2) {                                            
3090                                                         key[2].time= key[0].time;
3091                                                         psys_get_particle_on_path(scene, ob, psys, ptn[2].index, key + 2, 0);
3092                                                         VecMulf(key[2].co, weight[2]);
3093                                                         VECADD(key[0].co, key[0].co, key[2].co);
3094                                                 }
3095                                         }
3096
3097                                         if(k==0)
3098                                                 VECSUB(co1, pa->state.co, key[0].co);
3099
3100                                         VECADD(pa->hair[k].co, key[0].co, co1);
3101
3102                                         pa->hair[k].time= key[0].time;
3103                                 }
3104                         }
3105                         else {
3106                                 for(k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
3107                                         VECADDFAC(hkey->co, pa->state.co, pa->state.vel, k * framestep * timestep);
3108                                         pa->hair[k].time += k * framestep;
3109                                 }
3110                         }
3111                         for(k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
3112                                 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
3113                                 Mat4Invert(imat,hairmat);
3114                                 Mat4MulVecfl(imat, hkey->co);
3115                         }
3116                 }
3117                 edit->totkeys= psys_count_keys(psys);
3118
3119                 if(tree)
3120                         BLI_kdtree_free(tree);
3121         }
3122         if(add_pars)
3123                 MEM_freeN(add_pars);
3124         
3125         if(!psmd->dm->deformedOnly)
3126                 dm->release(dm);
3127 }
3128
3129 static void brush_weight(PEData *data, float mat[][4], float imat[][4], int pa_index, int key_index)
3130 {
3131         ParticleSystem *psys= data->psys;
3132         ParticleData *pa;
3133
3134         /* roots have full weight allways */
3135         if(key_index) {
3136                 pa= &psys->particles[pa_index];
3137                 pa->hair[key_index].weight= data->weightfac;
3138                 pa->flag |= PARS_EDIT_RECALC;
3139         }
3140 }
3141
3142 /************************* brush edit operator ********************/
3143
3144 typedef struct BrushEdit {
3145         Scene *scene;
3146         Object *ob;
3147         ParticleSystem *psys;
3148
3149         int first;
3150         int lastmouse[2];
3151 } BrushEdit;
3152
3153 static int brush_edit_init(bContext *C, wmOperator *op)
3154 {
3155         Scene *scene= CTX_data_scene(C);
3156         Object *ob= CTX_data_active_object(C);
3157         ParticleSystem *psys= PE_get_current(scene, ob);
3158         ParticleEditSettings *pset= PE_settings(scene);
3159         ARegion *ar= CTX_wm_region(C);
3160         BrushEdit *bedit;
3161
3162         if(pset->brushtype < 0)
3163                 return 0;
3164
3165         // XXX
3166         initgrabz(ar->regiondata, ob->obmat[3][0], ob->obmat[3][1], ob->obmat[3][2]);
3167
3168         bedit= MEM_callocN(sizeof(BrushEdit), "BrushEdit");
3169         bedit->first= 1;
3170         op->customdata= bedit;
3171
3172         bedit->scene= scene;
3173         bedit->ob= ob;
3174         bedit->psys= psys;
3175
3176         return 1;
3177 }
3178
3179 static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
3180 {
3181         BrushEdit *bedit= op->customdata;
3182         Scene *scene= bedit->scene;
3183         Object *ob= bedit->ob;
3184         ParticleSystem *psys= bedit->psys;
3185         ParticleEditSettings *pset= PE_settings(scene);
3186         ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
3187         ParticleBrushData *brush= &pset->brush[pset->brushtype];
3188         ARegion *ar= CTX_wm_region(C);
3189         float vec1[3], vec2[3];
3190         short mval[2], mvalo[2];
3191         int flip, mouse[2], dx, dy, removed= 0, selected= 0;
3192
3193         RNA_int_get_array(itemptr, "mouse", mouse);
3194         flip= RNA_boolean_get(itemptr, "flip");
3195
3196         bglFlush();
3197         glReadBuffer(GL_BACK);
3198         glDrawBuffer(GL_BACK);
3199 //              persp(PERSP_VIEW);
3200
3201         dx= mouse[0] - bedit->lastmouse[0];
3202         dy= mouse[1] - bedit->lastmouse[1];
3203
3204         mval[0]= mouse[0];
3205         mval[1]= mouse[1];
3206
3207         mvalo[0]= bedit->lastmouse[0];
3208         mvalo[1]= bedit->lastmouse[1];
3209
3210         if(((pset->brushtype == PE_BRUSH_ADD) ?
3211                 (sqrt(dx * dx + dy * dy) > pset->brush[PE_BRUSH_ADD].step) : (dx != 0 || dy != 0))
3212                 || bedit->first) {
3213
3214                 selected= (short)count_selected_keys(scene, psys);
3215
3216                 switch(pset->brushtype) {
3217                         case PE_BRUSH_COMB:
3218                         {
3219                                 PEData data;
3220
3221                                 PE_set_view3d_data(C, &data);
3222                                 data.mval= mval;
3223                                 data.rad= (float)brush->size;
3224
3225                                 data.combfac= (float)(brush->strength - 50) / 50.0f;
3226                                 if(data.combfac < 0.0f)
3227                                         data.combfac= 1.0f - 9.0f * data.combfac;
3228                                 else
3229                                         data.combfac= 1.0f - data.combfac;
3230
3231                                 Mat4Invert(ob->imat, ob->obmat);
3232
3233                                 window_to_3d(ar, vec1, mvalo[0], mvalo[1]);
3234                                 window_to_3d(ar, vec2, mval[0], mval[1]);
3235                                 VECSUB(vec1, vec2, vec1);
3236                                 data.dvec= vec1;