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