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