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