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