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