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