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