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