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