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