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