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