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