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