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