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