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