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