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