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