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