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