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