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