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