svn merge -r 13095:13148 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / src / editparticle.c
1 /* editparticle.c
2  *
3  *
4  * $Id: editparticle.c $
5  *
6  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version. The Blender
12  * Foundation also sells licenses for use in proprietary software under
13  * the Blender License.  See http://www.blender.org/BL/ for information
14  * about this.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  *
25  * The Original Code is Copyright (C) 2007 by Janne Karhu.
26  * All rights reserved.
27  *
28  * The Original Code is: all of this file.
29  *
30  * Contributor(s): none yet.
31  *
32  * ***** END GPL/BL DUAL LICENSE BLOCK *****
33  */
34
35 #include <stdlib.h>
36 #include <math.h>
37 #include <string.h>
38
39 #include "MEM_guardedalloc.h"
40
41 #include "DNA_scene_types.h"
42 #include "DNA_mesh_types.h"
43 #include "DNA_meshdata_types.h"
44 #include "DNA_modifier_types.h"
45 #include "DNA_object_force.h"
46 #include "DNA_object_types.h"
47 #include "DNA_vec_types.h"
48 #include "DNA_userdef_types.h"
49 #include "DNA_view3d_types.h"
50 #include "DNA_screen_types.h"
51 #include "DNA_space_types.h"
52
53 #include "BKE_bad_level_calls.h"
54 #include "BKE_DerivedMesh.h"
55 #include "BKE_depsgraph.h"
56
57 #include "BKE_global.h"
58 #include "BKE_object.h"
59 #include "BKE_mesh.h"
60 #include "BKE_modifier.h"
61 #include "BKE_particle.h"
62 #include "BKE_scene.h"
63 #include "BKE_utildefines.h" 
64
65 #include "BSE_edit.h"
66
67 #include "BLI_arithb.h"
68 #include "BLI_blenlib.h"
69 #include "BLI_dynstr.h"
70 #include "BLI_kdtree.h"
71 #include "BLI_rand.h"
72
73 #include "PIL_time.h"
74
75 #include "BIF_gl.h"
76 #include "BIF_glutil.h"
77 #include "BIF_graphics.h"
78 #include "BIF_editparticle.h"
79 #include "BIF_editview.h"
80 #include "BIF_interface.h"
81 #include "BIF_meshtools.h"
82 #include "BIF_mywindow.h"
83 #include "BIF_resources.h"
84 #include "BIF_screen.h"
85 #include "BIF_space.h"
86 #include "BIF_toolbox.h"
87
88 #include "BSE_view.h"
89
90 #include "BDR_editobject.h" //rightmouse_transform()
91 #include "BDR_drawobject.h"
92
93 #include "blendef.h"
94 #include "mydevice.h"
95
96 static void ParticleUndo_clear(ParticleSystem *psys);
97
98 #define LOOP_PARTICLES(i,pa) for(i=0, pa=psys->particles; i<totpart; i++, pa++)
99 #define LOOP_KEYS(k,key) if(psys->edit)for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++)
100
101 void PE_free_particle_edit(ParticleSystem *psys)
102 {
103         ParticleEdit *edit=psys->edit;
104         int i, totpart=psys->totpart;
105
106         if(edit==0) return;
107
108         ParticleUndo_clear(psys);
109
110         if(edit->keys){
111                 for(i=0; i<totpart; i++){
112                         if(edit->keys[i])
113                                 MEM_freeN(edit->keys[i]);
114                 }
115                 MEM_freeN(edit->keys);
116         }
117
118         if(edit->mirror_cache)
119                 MEM_freeN(edit->mirror_cache);
120
121         if(edit->emitter_cosnos){
122                 MEM_freeN(edit->emitter_cosnos);
123                 edit->emitter_cosnos=0;
124         }
125
126         if(edit->emitter_field){
127                 BLI_kdtree_free(edit->emitter_field);
128                 edit->emitter_field=0;
129         }
130
131         MEM_freeN(edit);
132
133         psys->edit=NULL;
134 }
135 /************************************************/
136 /*                      Edit Mode Helpers                                       */
137 /************************************************/
138 int PE_can_edit(ParticleSystem *psys)
139 {
140         return (psys && psys->edit && (G.f & G_PARTICLEEDIT));
141 }
142
143 ParticleEditSettings *PE_settings()
144 {
145         return &G.scene->toolsettings->particle;
146 }
147
148 void PE_change_act(void *ob_v, void *act_v)
149 {
150         Object *ob = ob_v;
151         ParticleSystem *psys;
152         short act = *((short*)act_v) - 1;
153
154         if((psys=psys_get_current(ob)))
155                 psys->flag &= ~PSYS_CURRENT;
156
157         if(act>=0){
158                 if((psys=BLI_findlink(&ob->particlesystem,act))) {
159                         psys->flag |= PSYS_CURRENT;
160
161                         if(psys_check_enabled(ob, psys)) {
162                                 if(G.f & G_PARTICLEEDIT && !psys->edit)
163                                         PE_create_particle_edit(ob, psys);
164                                 PE_recalc_world_cos(ob, psys);
165                         }
166                 }
167         }
168 }
169
170 /* always gets atleast the first particlesystem even if PSYS_CURRENT flag is not set */
171 ParticleSystem *PE_get_current(Object *ob)
172 {
173         ParticleSystem *psys;
174
175         if(ob==NULL)
176                 return NULL;
177
178         psys= ob->particlesystem.first;
179         while(psys){
180                 if(psys->flag & PSYS_CURRENT)
181                         break;
182                 psys=psys->next;
183         }
184
185         if(psys==NULL && ob->particlesystem.first){
186                 psys=ob->particlesystem.first;
187                 psys->flag |= PSYS_CURRENT;
188         }
189
190         if(psys && psys_check_enabled(ob, psys) && ob == OBACT && (G.f & G_PARTICLEEDIT))
191                 if(psys->part->type == PART_HAIR && psys->flag & PSYS_EDITED)
192                         if(psys->edit == NULL)
193                                 PE_create_particle_edit(ob, psys);
194
195         return psys;
196 }
197 /* returns -1 if no system has PSYS_CURRENT flag */
198 short PE_get_current_num(Object *ob)
199 {
200         short num=0;
201         ParticleSystem *psys = ob->particlesystem.first;
202
203         while(psys){
204                 if(psys->flag & PSYS_CURRENT)
205                         return num;
206                 num++;
207                 psys=psys->next;
208         }
209
210         return -1;
211 }
212
213 void PE_hide_keys_time(ParticleSystem *psys, float cfra)
214 {
215         ParticleData *pa;
216         ParticleEditKey *key;
217         ParticleEditSettings *pset=PE_settings();
218         int i,k,totpart=psys->totpart;
219
220         if(pset->draw_timed && G.scene->selectmode==SCE_SELECT_POINT){
221                 LOOP_PARTICLES(i,pa){
222                         LOOP_KEYS(k,key){
223                                 if(fabs(cfra-*key->time) < pset->draw_timed)
224                                         key->flag &= ~PEK_HIDE;
225                                 else{
226                                         key->flag |= PEK_HIDE;
227                                         key->flag &= ~PEK_SELECT;
228                                 }
229                         }
230                 }
231         }
232         else{
233                 LOOP_PARTICLES(i,pa){
234                         LOOP_KEYS(k,key){
235                                 key->flag &= ~PEK_HIDE;
236                         }
237                 }
238         }
239 }
240
241 static int key_inside_circle(short mco[2], float rad, float co[3], float *distance)
242 {
243         float dx,dy,dist;
244         short vertco[2];
245
246         project_short(co,vertco);
247         
248         if (vertco[0]==IS_CLIPPED)
249                 return 0;
250         
251         dx=(float)(mco[0]-vertco[0]);
252         dy=(float)(mco[1]-vertco[1]);
253         dist=(float)sqrt((double)(dx*dx + dy*dy));
254
255         if(dist<=rad){
256                 if(distance) *distance=dist;
257                 return 1;
258         }
259         else
260                 return 0;
261 }
262 static int key_inside_rect(rcti *rect, float co[3])
263 {
264         short vertco[2];
265
266         project_short(co,vertco);
267
268         if (vertco[0]==IS_CLIPPED)
269                 return 0;
270         
271         if(vertco[0] > rect->xmin && vertco[0] < rect->xmax &&
272                         vertco[1] > rect->ymin && vertco[1] < rect->ymax)
273                 return 1;
274         else
275                 return 0;
276 }
277 static int test_key_depth(float *co, bglMats *mats){
278         double ux, uy, uz;
279         float depth;
280         short wco[3], x,y;
281
282         if((G.vd->flag & V3D_ZBUF_SELECT)==0) return 1;
283
284         gluProject(co[0],co[1],co[2], mats->modelview, mats->projection,
285                         (GLint *)mats->viewport, &ux, &uy, &uz );
286
287         project_short(co,wco);
288         
289         if (wco[0]==IS_CLIPPED)
290                 return 0;
291         
292         x=wco[0];
293         y=wco[1];
294
295         if(G.vd->depths && x<G.vd->depths->w && y<G.vd->depths->h){
296                 if((float)uz>G.vd->depths->depths[y*G.vd->depths->w+x])
297                         return 0;
298                 else
299                         return 1;
300         }
301         else{
302                 x+= (short)curarea->winrct.xmin;
303                 y+= (short)curarea->winrct.ymin;
304
305                 glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
306
307                 if((float)uz>depth)
308                         return 0;
309                 else
310                         return 1;
311         }
312 }
313
314 static int particle_is_selected(ParticleSystem *psys, ParticleData *pa)
315 {
316         ParticleEditKey *key;
317         int sel, i, k;
318
319         if(pa->flag&PARS_HIDE) return 0;
320
321         sel=0;
322         i= pa - psys->particles;
323         LOOP_KEYS(k,key)
324                 if(key->flag&PEK_SELECT)
325                         return 1;
326         
327         return 0;
328 }
329
330 /*-----iterators over editable particles-----*/
331 static void for_mouse_hit_keys(int nearest, ParticleSystem *psys, void (*func)(ParticleSystem *psys, int pa_index, int key_index, void *userData), void *userData){
332         /* these are allways the first in this userData */
333         struct { short *mval; float rad; rcti *rect;} *data = userData;
334         ParticleData *pa;
335         ParticleEditKey *key;
336         bglMats mats;
337         int i,k, totpart, nearest_pa=-1, nearest_key=-1;
338         float dist=data->rad;
339
340         if(psys==0 || G.scene->selectmode==SCE_SELECT_PATH) return;
341
342         totpart=psys->totpart;
343
344         bgl_get_mats(&mats);
345
346         LOOP_PARTICLES(i,pa){
347                 if(pa->flag & PARS_HIDE) continue;
348
349                 if(G.scene->selectmode==SCE_SELECT_END){
350                         key=psys->edit->keys[i]+pa->totkey-1;
351
352                         if(nearest){
353                                 if(key_inside_circle(data->mval,dist,key->world_co,&dist) && test_key_depth(key->world_co,&mats)){
354                                         nearest_pa=i;
355                                         nearest_key=pa->totkey-1;
356                                 }
357                         }
358                         else if(((data->mval)?
359                                                 key_inside_circle(data->mval,data->rad,key->world_co,0):
360                                                 key_inside_rect(data->rect,key->world_co)) && test_key_depth(key->world_co,&mats))
361                                 func(psys,i,pa->totkey-1,userData);
362                 }
363                 else{
364                         key=psys->edit->keys[i];
365
366                         LOOP_KEYS(k,key){
367                                 if(key->flag&PEK_HIDE) continue;
368
369                                 if(nearest){
370                                         if(key_inside_circle(data->mval,dist,key->world_co,&dist) && test_key_depth(key->world_co,&mats)){
371                                                 nearest_pa=i;
372                                                 nearest_key=k;
373                                         }
374                                 }
375                                 else if(((data->mval)?
376                                                         key_inside_circle(data->mval,data->rad,key->world_co,0):
377                                                         key_inside_rect(data->rect,key->world_co)) && test_key_depth(key->world_co,&mats))
378                                         func(psys,i,k,userData);
379                         }
380                 }
381         }
382         if(nearest && nearest_pa>-1){
383                 func(psys,nearest_pa,nearest_key,userData);
384         }
385 }
386 static void foreach_mouse_hit_element(int selected, ParticleSystem *psys,void (*func)(ParticleSystem *psys, int index, void *userData), void *userData){
387         /* these are allways the first in this userData */
388         struct { short *mval; float rad; rcti* rect; float dist;} *data = userData;
389         ParticleData *pa;
390         ParticleEditKey *key;
391         bglMats mats;
392         int i,k, totpart;
393
394         if(psys==0) return;
395
396         totpart=psys->totpart;
397
398         bgl_get_mats(&mats);
399
400         if(G.scene->selectmode==SCE_SELECT_PATH)
401                 selected=0;
402
403         LOOP_PARTICLES(i,pa){
404                 if(pa->flag & PARS_HIDE) continue;
405
406                 if(G.scene->selectmode==SCE_SELECT_END){
407                         key=psys->edit->keys[i]+pa->totkey-1;
408                         if(key_inside_circle(data->mval,data->rad,key->world_co,&data->dist) && (selected==0 || key->flag&PEK_SELECT) && test_key_depth(key->world_co,&mats))
409                                 func(psys,i,userData);
410                 }
411                 else{
412                         LOOP_KEYS(k,key){
413                                 if(key->flag&PEK_HIDE) continue;
414
415                                 if(key_inside_circle(data->mval,data->rad,key->world_co,&data->dist) && (selected==0 || key->flag&PEK_SELECT) && test_key_depth(key->world_co,&mats)){
416                                         func(psys,i,userData);
417                                         break;
418                                 }
419                         }
420                 }
421         }
422 }
423 static void foreach_mouse_hit_key(int selected, ParticleSystem *psys,void (*func)(ParticleSystem *psys, float mat[][4], float imat[][4], int bel_index, int key_index, void *userData), void *userData){
424         /* these are allways the first in this userData */
425         struct { Object *ob; short *mval; float rad; rcti* rect; float dist;} *data = userData;
426         ParticleData *pa;
427         ParticleEditKey *key;
428         ParticleSystemModifierData *psmd=0;
429         bglMats mats;
430         int i,k, totpart;
431         float mat[4][4], imat[4][4];
432
433         if(psys==0) return;
434
435         psmd=psys_get_modifier(data->ob,psys);
436
437         totpart=psys->totpart;
438
439         bgl_get_mats(&mats);
440
441         if(G.scene->selectmode==SCE_SELECT_PATH)
442                 selected=0;
443
444         Mat4One(imat);
445         Mat4One(mat);
446
447         LOOP_PARTICLES(i,pa){
448                 if(pa->flag & PARS_HIDE) continue;
449
450                 psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, pa, mat);
451                 //psys_geometry_mat(psmd->dm,pa,tmat);
452                 //Mat4MulMat4(mat,tmat,data->ob->obmat);
453                 Mat4Invert(imat,mat);
454
455                 if(G.scene->selectmode==SCE_SELECT_END){
456                         key=psys->edit->keys[i]+pa->totkey-1;
457                         if(key_inside_circle(data->mval,data->rad,key->world_co,&data->dist) && (selected==0 || key->flag&PEK_SELECT) && test_key_depth(key->world_co,&mats))
458                                 func(psys,mat,imat,i,pa->totkey-1,userData);
459                 }
460                 else{
461                         LOOP_KEYS(k,key){
462                                 if(key->flag&PEK_HIDE) continue;
463
464                                 if(key_inside_circle(data->mval,data->rad,key->world_co,&data->dist) && (selected==0 || key->flag&PEK_SELECT) && test_key_depth(key->world_co,&mats)){
465                                         func(psys,mat,imat,i,k,userData);
466                                 }
467                         }
468                 }
469         }
470 }
471 static void foreach_selected_element(ParticleSystem *psys, void (*func)(ParticleSystem *psys, int index, void *userData), void *userData){
472         ParticleData *pa;
473         int i,totpart;
474
475         if(psys==0) return;
476
477         totpart=psys->totpart;
478
479         LOOP_PARTICLES(i,pa)
480                 if(particle_is_selected(psys, pa))
481                         func(psys,i,userData);
482 }
483 static void foreach_selected_key(ParticleSystem *psys, void (*func)(ParticleSystem *psys, int pa_index, int key_index, void *userData), void *userData){
484         ParticleData *pa;
485         ParticleEditKey *key;
486         int i,k,totpart;
487
488         if(psys==0) return;
489
490         totpart=psys->totpart;
491
492         LOOP_PARTICLES(i,pa){
493                 if(pa->flag&PARS_HIDE) continue;
494
495                 key=psys->edit->keys[i];
496                 LOOP_KEYS(k,key){
497                         if(key->flag&PEK_SELECT)
498                                 func(psys,i,k,userData);
499                 }
500         }
501 }
502 void PE_foreach_element(ParticleSystem *psys, void (*func)(ParticleSystem *psys, int index, void *userData), void *userData)
503 {
504         int i,totpart;
505
506         if(psys==0) return;
507
508         totpart=psys->totpart;
509
510         for(i=0; i<totpart; i++)
511                 func(psys,i,userData);
512 }
513 static int count_selected_keys(ParticleSystem *psys)
514 {
515         ParticleData *pa;
516         ParticleEditKey *key;
517         int i,k,totpart,sel=0;
518
519         if(psys==0) return 0;
520
521         totpart=psys->totpart;
522
523         LOOP_PARTICLES(i,pa){
524                 if(pa->flag&PARS_HIDE) continue;
525
526                 key=psys->edit->keys[i];
527                 if(G.scene->selectmode==SCE_SELECT_POINT){
528                         for(k=0; k<pa->totkey; k++,key++){
529                                 if(key->flag&PEK_SELECT)
530                                         sel++;
531                         }
532                 }
533                 else if(G.scene->selectmode==SCE_SELECT_END){
534                         key+=pa->totkey-1;
535                         if(key->flag&PEK_SELECT)
536                                 sel++;
537                 }
538         }
539         return sel;
540 }
541
542 /************************************************/
543 /*                      Particle Edit Mirroring                         */
544 /************************************************/
545
546 static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
547 {
548         ParticleEdit *edit;
549         ParticleData *pa;
550         ParticleSystemModifierData *psmd;
551         KDTree *tree;
552         KDTreeNearest nearest;
553         float mat[4][4], co[3];
554         int i, index, totpart;
555
556         edit= psys->edit;
557         psmd= psys_get_modifier(ob, psys);
558         totpart= psys->totpart;
559
560         tree= BLI_kdtree_new(totpart);
561
562         /* insert particles into kd tree */
563         LOOP_PARTICLES(i,pa) {
564                 psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat);
565                 VECCOPY(co, pa->hair[0].co);
566                 Mat4MulVecfl(mat, co);
567                 BLI_kdtree_insert(tree, i, co, NULL);
568         }
569
570         BLI_kdtree_balance(tree);
571
572         /* lookup particles and set in mirror cache */
573         if(!edit->mirror_cache)
574                 edit->mirror_cache= MEM_callocN(sizeof(int)*totpart, "PE mirror cache");
575         
576         LOOP_PARTICLES(i,pa) {
577                 psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat);
578                 VECCOPY(co, pa->hair[0].co);
579                 Mat4MulVecfl(mat, co);
580                 co[0]= -co[0];
581
582                 index= BLI_kdtree_find_nearest(tree, co, NULL, &nearest);
583
584                 /* this needs a custom threshold still, duplicated for editmode mirror */
585                 if(index != -1 && index != i && (nearest.dist <= 0.0002f))
586                         edit->mirror_cache[i]= index;
587                 else
588                         edit->mirror_cache[i]= -1;
589         }
590
591         /* make sure mirrors are in two directions */
592         LOOP_PARTICLES(i,pa) {
593                 if(edit->mirror_cache[i]) {
594                         index= edit->mirror_cache[i];
595                         if(edit->mirror_cache[index] != i)
596                                 edit->mirror_cache[i]= -1;
597                 }
598         }
599
600         BLI_kdtree_free(tree);
601 }
602
603 static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys, ParticleData *pa, ParticleData *mpa)
604 {
605         HairKey *hkey, *mhkey;
606         ParticleEditKey *key, *mkey;
607         ParticleEdit *edit;
608         float mat[4][4], mmat[4][4], immat[4][4];
609         int i, mi, k;
610
611         edit= psys->edit;
612         i= pa - psys->particles;
613
614         if(!edit->mirror_cache)
615                 PE_update_mirror_cache(ob, psys);
616
617         /* find mirrored particle if needed */
618         if(!mpa) {
619                 mi= edit->mirror_cache[i];
620                 if(mi == -1)
621                         return;
622                 mpa= psys->particles + mi;
623         }
624         else
625                 mi= mpa - psys->particles;
626
627         /* make sure they have the same amount of keys */
628         if(pa->totkey != mpa->totkey) {
629                 if(mpa->hair) MEM_freeN(mpa->hair);
630                 if(edit->keys[mi]) MEM_freeN(edit->keys[mi]);
631
632                 mpa->hair= MEM_dupallocN(pa->hair);
633                 edit->keys[mi]= MEM_dupallocN(edit->keys[i]);
634                 mpa->totkey= pa->totkey;
635
636                 mhkey= mpa->hair;
637                 mkey= edit->keys[mi];
638                 for(k=0; k<mpa->totkey; k++, mkey++, mhkey++) {
639                         mkey->co= mhkey->co;
640                         mkey->time= &mhkey->time;
641                         mkey->flag &= PEK_SELECT;
642                 }
643         }
644
645         /* mirror positions and tags */
646         psys_mat_hair_to_orco(ob, dm, psys->part->from, pa, mat);
647         psys_mat_hair_to_orco(ob, dm, psys->part->from, mpa, mmat);
648         Mat4Invert(immat, mmat);
649
650         hkey=pa->hair;
651         mhkey=mpa->hair;
652         key= edit->keys[i];
653         mkey= edit->keys[mi];
654         for(k=0; k<pa->totkey; k++, hkey++, mhkey++, key++, mkey++) {
655                 VECCOPY(mhkey->co, hkey->co);
656                 Mat4MulVecfl(mat, mhkey->co);
657                 mhkey->co[0]= -mhkey->co[0];
658                 Mat4MulVecfl(immat, mhkey->co);
659
660                 if(key->flag & PEK_TAG)
661                         mkey->flag |= PEK_TAG;
662         }
663
664         if(pa->flag & PARS_TAG)
665                 mpa->flag |= PARS_TAG;
666         if(pa->flag & PARS_EDIT_RECALC)
667                 mpa->flag |= PARS_EDIT_RECALC;
668 }
669
670 static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
671 {
672         ParticleEdit *edit;
673         ParticleData *pa;
674         ParticleSystemModifierData *psmd;
675         int i, totpart;
676
677         edit= psys->edit;
678         psmd= psys_get_modifier(ob, psys);
679         totpart= psys->totpart;
680
681         /* we delay settings the PARS_EDIT_RECALC for mirrored particles
682          * to avoid doing mirror twice */
683         LOOP_PARTICLES(i,pa) {
684                 if(pa->flag & PARS_EDIT_RECALC) {
685                         PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
686
687                         if(edit->mirror_cache[i] != -1)
688                                 psys->particles[edit->mirror_cache[i]].flag &= ~PARS_EDIT_RECALC;
689                 }
690         }
691
692         LOOP_PARTICLES(i,pa)
693                 if(pa->flag & PARS_EDIT_RECALC)
694                         if(edit->mirror_cache[i] != -1)
695                                 psys->particles[edit->mirror_cache[i]].flag |= PARS_EDIT_RECALC;
696
697         edit->totkeys= psys_count_keys(psys);
698 }
699
700 /************************************************/
701 /*                      Edit Calculation                                        */
702 /************************************************/
703 /* tries to stop edited particles from going through the emitter's surface */
704 static void PE_deflect_emitter(Object *ob, ParticleSystem *psys)
705 {
706         ParticleEdit *edit;
707         ParticleData *pa;
708         ParticleEditKey *key;
709         ParticleEditSettings *pset = PE_settings();
710         ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys);
711         int i,k,totpart,index;
712         float *vec, *nor, dvec[3], dot, dist_1st;
713         float hairimat[4][4], hairmat[4][4];
714
715         if(psys==0)
716                 return;
717
718         if((pset->flag & PE_DEFLECT_EMITTER)==0)
719                 return;
720
721         edit=psys->edit;
722         totpart=psys->totpart;
723
724         LOOP_PARTICLES(i,pa){
725                 if(!(pa->flag & PARS_EDIT_RECALC))
726                         continue;
727                 
728                 psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, hairmat);
729                 
730                 LOOP_KEYS(k,key){
731                         Mat4MulVecfl(hairmat, key->co);
732                 }
733         //}
734
735         //LOOP_PARTICLES(i,pa){
736                 key=psys->edit->keys[i]+1;
737
738                 dist_1st=VecLenf((key-1)->co,key->co);
739                 dist_1st*=0.75f*pset->emitterdist;
740
741                 for(k=1; k<pa->totkey; k++, key++){
742                         index= BLI_kdtree_find_nearest(edit->emitter_field,key->co,NULL,NULL);
743                         
744                         vec=edit->emitter_cosnos +index*6;
745                         nor=vec+3;
746
747                         VecSubf(dvec, key->co, vec);
748
749                         dot=Inpf(dvec,nor);
750                         VECCOPY(dvec,nor);
751
752                         if(dot>0.0f){
753                                 if(dot<dist_1st){
754                                         Normalize(dvec);
755                                         VecMulf(dvec,dist_1st-dot);
756                                         VecAddf(key->co,key->co,dvec);
757                                 }
758                         }
759                         else{
760                                 Normalize(dvec);
761                                 VecMulf(dvec,dist_1st-dot);
762                                 VecAddf(key->co,key->co,dvec);
763                         }
764                         if(k==1)
765                                 dist_1st*=1.3333f;
766                 }
767         //}
768
769         //LOOP_PARTICLES(i,pa){
770                 
771                 Mat4Invert(hairimat,hairmat);
772
773                 LOOP_KEYS(k,key){
774                         Mat4MulVecfl(hairimat, key->co);
775                 }
776         }
777 }
778 /* force set distances between neighbouring keys */
779 void PE_apply_lengths(ParticleSystem *psys)
780 {
781         ParticleEdit *edit;
782         ParticleData *pa;
783         ParticleEditKey *key;
784         ParticleEditSettings *pset=PE_settings();
785         int i,k,totpart;
786         float dv1[3];
787
788         if(psys==0)
789                 return;
790
791         if((pset->flag & PE_KEEP_LENGTHS)==0)
792                 return;
793
794         edit=psys->edit;
795         totpart=psys->totpart;
796
797         LOOP_PARTICLES(i,pa){
798                 if(!(pa->flag & PARS_EDIT_RECALC))
799                         continue;
800                 
801                 for(k=1, key=edit->keys[i] + 1; k<pa->totkey; k++, key++){
802                         VecSubf(dv1, key->co, (key - 1)->co);
803                         Normalize(dv1);
804                         VecMulf(dv1, (key - 1)->length);
805                         VecAddf(key->co, (key - 1)->co, dv1);
806                 }
807         }
808 }
809 /* try to find a nice solution to keep distances between neighbouring keys */
810 static void PE_iterate_lengths(ParticleSystem *psys)
811 {
812         ParticleEdit *edit;
813         ParticleData *pa;
814         ParticleEditKey *key;
815         ParticleEditSettings *pset=PE_settings();
816         int i, j, k,totpart;
817         float tlen;
818         float dv0[3] = {0.0f, 0.0f, 0.0f};
819         float dv1[3] = {0.0f, 0.0f, 0.0f};
820         float dv2[3] = {0.0f, 0.0f, 0.0f};
821
822         if(psys==0)
823                 return;
824
825         if((pset->flag & PE_KEEP_LENGTHS)==0)
826                 return;
827
828         edit=psys->edit;
829         totpart=psys->totpart;
830
831         LOOP_PARTICLES(i,pa){
832                 if(!(pa->flag & PARS_EDIT_RECALC))
833                         continue;
834
835                 for(j=1; j<pa->totkey; j++){
836                         float mul = 1.0f / (float)pa->totkey;
837
838                         if(pset->flag & PE_LOCK_FIRST){
839                                 key = edit->keys[i] + 1;
840                                 k = 1;
841                                 dv1[0] = dv1[1] = dv1[2] = 0.0;
842                         }
843                         else{
844                                 key = edit->keys[i];
845                                 k = 0;
846                                 dv0[0] = dv0[1] = dv0[2] = 0.0;
847                         }
848
849                         for(; k<pa->totkey; k++, key++){
850                                 if(k){
851                                         VecSubf(dv0, (key - 1)->co, key->co);
852                                         tlen = Normalize(dv0);
853                                         VecMulf(dv0, (mul * (tlen - (key - 1)->length)));
854                                 }
855
856                                 if(k < pa->totkey - 1){
857                                         VecSubf(dv2, (key + 1)->co, key->co);
858                                         tlen = Normalize(dv2);
859                                         VecMulf(dv2, mul * (tlen - key->length));
860                                 }
861
862                                 if(k){
863                                         VecAddf((key-1)->co,(key-1)->co,dv1);
864                                 }
865
866                                 VECADD(dv1,dv0,dv2);
867                         }
868                 }
869         }
870 }
871 /* set current distances to be kept between neighbouting keys */
872 static void recalc_lengths(ParticleSystem *psys)
873 {
874         ParticleData *pa;
875         ParticleEditKey *key;
876         int i, k, totpart;
877
878         if(psys==0)
879                 return;
880
881         totpart = psys->totpart;
882
883         LOOP_PARTICLES(i,pa){
884                 key = psys->edit->keys[i];
885                 for(k=0; k<pa->totkey-1; k++, key++){
886                         key->length = VecLenf(key->co, (key + 1)->co);
887                 }
888         }
889 }
890 /* calculate and store key locations in world coordinates */
891 void PE_recalc_world_cos(Object *ob, ParticleSystem *psys)
892 {
893         ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
894         ParticleData *pa;
895         ParticleEditKey *key;
896         int i, k, totpart;
897         float hairmat[4][4];
898
899         if(psys==0)
900                 return;
901
902         totpart = psys->totpart;
903
904         LOOP_PARTICLES(i,pa){
905                 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
906
907                 LOOP_KEYS(k,key){
908                         VECCOPY(key->world_co,key->co);
909                         Mat4MulVecfl(hairmat, key->world_co);
910                 }
911         }
912 }
913 /* calculate a tree for finding nearest emitter's vertice */
914 static void recalc_emitter_field(Object *ob, ParticleSystem *psys)
915 {
916         DerivedMesh *dm=psys_get_modifier(ob,psys)->dm;
917         ParticleEdit *edit = psys->edit;
918         MFace *mface;
919         MVert *mvert;
920         float *vec, *nor;
921         int i, totface, totvert;
922
923         if(edit->emitter_cosnos)
924                 MEM_freeN(edit->emitter_cosnos);
925
926         BLI_kdtree_free(edit->emitter_field);
927
928         totface=dm->getNumFaces(dm);
929         totvert=dm->getNumVerts(dm);
930
931         edit->emitter_cosnos=MEM_callocN(totface*6*sizeof(float),"emitter cosnos");
932
933         edit->emitter_field= BLI_kdtree_new(totface);
934
935         vec=edit->emitter_cosnos;
936         nor=vec+3;
937
938         mvert=dm->getVertDataArray(dm,CD_MVERT);
939         for(i=0; i<totface; i++, vec+=6, nor+=6){
940                 mface=dm->getFaceData(dm,i,CD_MFACE);
941
942                 mvert=dm->getVertData(dm,mface->v1,CD_MVERT);
943                 VECCOPY(vec,mvert->co);
944                 VECCOPY(nor,mvert->no);
945
946                 mvert=dm->getVertData(dm,mface->v2,CD_MVERT);
947                 VECADD(vec,vec,mvert->co);
948                 VECADD(nor,nor,mvert->no);
949
950                 mvert=dm->getVertData(dm,mface->v3,CD_MVERT);
951                 VECADD(vec,vec,mvert->co);
952                 VECADD(nor,nor,mvert->no);
953
954                 if (mface->v4){
955                         mvert=dm->getVertData(dm,mface->v4,CD_MVERT);
956                         VECADD(vec,vec,mvert->co);
957                         VECADD(nor,nor,mvert->no);
958                         
959                         VecMulf(vec,0.25);
960                 }
961                 else
962                         VecMulf(vec,0.3333f);
963
964                 Normalize(nor);
965
966                 BLI_kdtree_insert(edit->emitter_field, i, vec, NULL);
967         }
968
969         BLI_kdtree_balance(edit->emitter_field);
970 }
971
972 void PE_update_selection(Object *ob, int useflag)
973 {
974         ParticleSystem *psys= PE_get_current(ob);
975         ParticleEdit *edit= psys->edit;
976         ParticleEditSettings *pset= PE_settings();
977         ParticleSettings *part= psys->part;
978         ParticleData *pa;
979         HairKey *hkey;
980         ParticleEditKey *key;
981         float cfra= CFRA;
982         int i, k, totpart;
983
984         totpart= psys->totpart;
985
986         /* flag all particles to be updated if not using flag */
987         if(!useflag)
988                 LOOP_PARTICLES(i,pa)
989                         pa->flag |= PARS_EDIT_RECALC;
990
991         /* flush edit key flag to hair key flag to preserve selection 
992          * on save */
993         LOOP_PARTICLES(i,pa) {
994                 key = edit->keys[i];
995
996                 for(k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, key++)
997                         hkey->editflag= key->flag;
998         }
999
1000         psys_cache_paths(ob, psys, CFRA, 1);
1001
1002         if(part->childtype && (pset->flag & PE_SHOW_CHILD))
1003                 psys_cache_child_paths(ob, psys, cfra, 1);
1004
1005         /* disable update flag */
1006         LOOP_PARTICLES(i,pa)
1007                 pa->flag &= ~PARS_EDIT_RECALC;
1008 }
1009
1010 void PE_update_object(Object *ob, int useflag)
1011 {
1012         ParticleSystem *psys= PE_get_current(ob);
1013         ParticleEditSettings *pset= PE_settings();
1014         ParticleSettings *part= psys->part;
1015         ParticleData *pa;
1016         float cfra= CFRA;
1017         int i, totpart= psys->totpart;
1018
1019         /* flag all particles to be updated if not using flag */
1020         if(!useflag)
1021                 LOOP_PARTICLES(i,pa)
1022                         pa->flag |= PARS_EDIT_RECALC;
1023
1024         /* do post process on particle edit keys */
1025         PE_iterate_lengths(psys);
1026         PE_deflect_emitter(ob,psys);
1027         PE_apply_lengths(psys);
1028         if(pset->flag & PE_X_MIRROR)
1029                 PE_apply_mirror(ob,psys);
1030         PE_recalc_world_cos(ob,psys);
1031         PE_hide_keys_time(psys,cfra);
1032
1033         /* regenerate path caches */
1034         psys_cache_paths(ob, psys, cfra, 1);
1035
1036         if(part->childtype && (pset->flag & PE_SHOW_CHILD))
1037                 psys_cache_child_paths(ob, psys, cfra, 1);
1038
1039         /* disable update flag */
1040         LOOP_PARTICLES(i,pa)
1041                 pa->flag &= ~PARS_EDIT_RECALC;
1042 }
1043
1044 /* initialize needed data for bake edit */
1045 void PE_create_particle_edit(Object *ob, ParticleSystem *psys)
1046 {
1047         ParticleEdit *edit=psys->edit;
1048         ParticleData *pa;
1049         ParticleEditKey *key;
1050         HairKey *hkey;
1051         int i,k, totpart=psys->totpart, alloc=1;
1052
1053         if((psys->flag & PSYS_EDITED)==0)
1054                 return;
1055
1056         if(edit){
1057                 int newtotkeys = psys_count_keys(psys);
1058                 if(newtotkeys == edit->totkeys)
1059                         alloc=0;
1060         }
1061
1062         if(alloc){
1063                 if(edit){
1064                         error("ParticleEdit exists allready! Poke jahka!");
1065                         PE_free_particle_edit(psys);
1066                 }
1067
1068                 edit=psys->edit=MEM_callocN(sizeof(ParticleEdit), "PE_create_particle_edit");
1069
1070                 edit->keys=MEM_callocN(totpart*sizeof(ParticleEditKey*),"ParticleEditKey array");
1071
1072                 LOOP_PARTICLES(i,pa){
1073                         key = edit->keys[i] = MEM_callocN(pa->totkey*sizeof(ParticleEditKey),"ParticleEditKeys");
1074                         for(k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, key++){
1075                                 key->co = hkey->co;
1076                                 key->time = &hkey->time;
1077                                 key->flag= hkey->editflag;
1078                         }
1079                 }
1080
1081                 edit->totkeys = psys_count_keys(psys);
1082         }
1083
1084         recalc_lengths(psys);
1085         recalc_emitter_field(ob, psys);
1086         PE_recalc_world_cos(ob, psys);
1087
1088         if(alloc) {
1089                 ParticleUndo_clear(psys);
1090                 PE_undo_push("Original");
1091         }
1092 }
1093
1094 /* toggle particle mode on & off */
1095 void PE_set_particle_edit(void)
1096 {
1097         Object *ob= OBACT;
1098         ParticleSystem *psys = PE_get_current(ob);
1099
1100         scrarea_queue_headredraw(curarea);
1101         
1102         //if(!ob || ob->id.lib) return; /* is the id.lib test needed? -jahka*/
1103         if(ob==0 || psys==0) return;
1104         
1105         if(psys==0){
1106                 if(ob->particlesystem.first){
1107                         psys=ob->particlesystem.first;
1108                         psys->flag |= PSYS_CURRENT;
1109                 }
1110                 else
1111                         return;
1112         }
1113
1114         if((G.f & G_PARTICLEEDIT)==0){
1115                 if(psys && psys->part->type == PART_HAIR && psys->flag & PSYS_EDITED) {
1116                         if(psys_check_enabled(ob, psys)) {
1117                                 if(psys->edit==0)
1118                                         PE_create_particle_edit(ob, psys);
1119                                 PE_recalc_world_cos(ob, psys);
1120                         }
1121                 }
1122
1123                 G.f |= G_PARTICLEEDIT;
1124         }
1125         else{
1126                 G.f &= ~G_PARTICLEEDIT;
1127
1128                 if(psys->soft)
1129                         psys->softflag |= OB_SB_REDO;
1130         }
1131
1132         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
1133
1134         allqueue(REDRAWVIEW3D, 1);      /* including header */
1135         allqueue(REDRAWBUTSOBJECT, 0);
1136 }
1137 /************************************************/
1138 /*                      Edit Selections                                         */
1139 /************************************************/
1140 /*-----selection callbacks-----*/
1141 static void select_key(ParticleSystem *psys, int pa_index, int key_index, void *userData)
1142 {
1143         struct { short *mval; float rad; rcti* rect; int select; } *data = userData;
1144         ParticleData *pa = psys->particles + pa_index;
1145         ParticleEditKey *key = psys->edit->keys[pa_index] + key_index;
1146
1147         if(data->select)
1148                 key->flag|=PEK_SELECT;
1149         else
1150                 key->flag&=~PEK_SELECT;
1151
1152         pa->flag |= PARS_EDIT_RECALC;
1153 }
1154 static void select_keys(ParticleSystem *psys, int pa_index, int key_index, void *userData)
1155 {
1156         struct { short *mval; float rad; rcti* rect; int select; } *data = userData;
1157         ParticleData *pa = psys->particles + pa_index;
1158         ParticleEditKey *key = psys->edit->keys[pa_index];
1159         int k;
1160
1161         for(k=0; k<pa->totkey; k++,key++){
1162                 if(data->select)
1163                         key->flag|=PEK_SELECT;
1164                 else
1165                         key->flag&=~PEK_SELECT;
1166         }
1167
1168         pa->flag |= PARS_EDIT_RECALC;
1169 }
1170 static void toggle_key_select(ParticleSystem *psys, int pa_index, int key_index, void *userData)
1171 {
1172         ParticleData *pa = psys->particles + pa_index;
1173
1174         if(psys->edit->keys[pa_index][key_index].flag&PEK_SELECT)
1175                 psys->edit->keys[pa_index][key_index].flag&=~PEK_SELECT;
1176         else
1177                 psys->edit->keys[pa_index][key_index].flag|=PEK_SELECT;
1178         
1179         pa->flag |= PARS_EDIT_RECALC;
1180 }
1181 static void select_root(ParticleSystem *psys, int index, void *userData)
1182 {
1183         psys->edit->keys[index]->flag |= PEK_SELECT;
1184 }
1185
1186 static void select_tip(ParticleSystem *psys, int index, void *userData)
1187 {
1188         ParticleData *pa = psys->particles + index;
1189         ParticleEditKey *key = psys->edit->keys[index] + pa->totkey-1;
1190
1191         key->flag |= PEK_SELECT;
1192 }
1193 static void select_more_keys(ParticleSystem *psys, int index, void *userData)
1194 {
1195         ParticleEdit *edit = psys->edit;
1196         ParticleData *pa = psys->particles+index;
1197         ParticleEditKey *key;
1198         int k;
1199
1200         for(k=0,key=edit->keys[index]; k<pa->totkey; k++,key++){
1201                 if(key->flag&PEK_SELECT) continue;
1202
1203                 if(k==0){
1204                         if((key+1)->flag&PEK_SELECT)
1205                                 key->flag |= PEK_TO_SELECT;
1206                 }
1207                 else if(k==pa->totkey-1){
1208                         if((key-1)->flag&PEK_SELECT)
1209                                 key->flag |= PEK_TO_SELECT;
1210                 }
1211                 else{
1212                         if(((key-1)->flag | (key+1)->flag) & PEK_SELECT)
1213                                 key->flag |= PEK_TO_SELECT;
1214                 }
1215         }
1216
1217         for(k=0,key=edit->keys[index]; k<pa->totkey; k++,key++){
1218                 if(key->flag&PEK_TO_SELECT){
1219                         key->flag &= ~PEK_TO_SELECT;
1220                         key->flag |= PEK_SELECT;
1221                 }
1222         }
1223 }
1224
1225 static void select_less_keys(ParticleSystem *psys, int index, void *userData)
1226 {
1227         ParticleEdit *edit = psys->edit;
1228         ParticleData *pa = psys->particles+index;
1229         ParticleEditKey *key;
1230         int k;
1231
1232         for(k=0,key=edit->keys[index]; k<pa->totkey; k++,key++){
1233                 if((key->flag&PEK_SELECT)==0) continue;
1234
1235                 if(k==0){
1236                         if(((key+1)->flag&PEK_SELECT)==0)
1237                                 key->flag |= PEK_TO_SELECT;
1238                 }
1239                 else if(k==pa->totkey-1){
1240                         if(((key-1)->flag&PEK_SELECT)==0)
1241                                 key->flag |= PEK_TO_SELECT;
1242                 }
1243                 else{
1244                         if((((key-1)->flag & (key+1)->flag) & PEK_SELECT)==0)
1245                                 key->flag |= PEK_TO_SELECT;
1246                 }
1247         }
1248
1249         for(k=0,key=edit->keys[index]; k<pa->totkey; k++,key++){
1250                 if(key->flag&PEK_TO_SELECT)
1251                         key->flag &= ~(PEK_TO_SELECT|PEK_SELECT);
1252         }
1253 }
1254
1255 /*-----using above callbacks-----*/
1256 void PE_deselectall(void)
1257 {
1258         Object *ob = OBACT;
1259         ParticleSystem *psys = PE_get_current(ob);
1260         ParticleEdit *edit = 0;
1261         ParticleData *pa;
1262         ParticleEditKey *key;
1263         int i,k,totpart, sel = 0;
1264                 
1265         if(!PE_can_edit(psys)) return;
1266         
1267         edit = psys->edit;
1268
1269         totpart = psys->totpart;
1270         
1271         LOOP_PARTICLES(i,pa){
1272                 if(pa->flag & PARS_HIDE) continue;
1273                 LOOP_KEYS(k,key){
1274                         if(key->flag&PEK_SELECT){
1275                                 sel = 1;
1276                                 key->flag &= ~PEK_SELECT;
1277                                 pa->flag |= PARS_EDIT_RECALC;
1278                         }
1279                 }
1280         }
1281
1282         if(sel==0){
1283                 LOOP_PARTICLES(i,pa){
1284                         if(pa->flag & PARS_HIDE) continue;
1285                         LOOP_KEYS(k,key){
1286                                 if(!(key->flag & PEK_SELECT)) {
1287                                         key->flag |= PEK_SELECT;
1288                                         pa->flag |= PARS_EDIT_RECALC;
1289                                 }
1290                         }
1291                 }
1292         }
1293
1294         PE_update_selection(ob, 1);
1295
1296         BIF_undo_push("(De)select all keys");
1297         allqueue(REDRAWVIEW3D, 1);
1298 }
1299 void PE_mouse_particles(void)
1300 {
1301         struct { short *mval; float rad; rcti* rect; int select; } data;
1302         Object *ob = OBACT;
1303         ParticleSystem *psys = PE_get_current(ob);
1304         ParticleEdit *edit = 0;
1305         ParticleData *pa;
1306         ParticleEditKey *key;
1307         short mval[2];
1308         int i,k,totpart;
1309
1310         if(!PE_can_edit(psys)) return;
1311
1312         edit = psys->edit;
1313
1314         totpart = psys->totpart;
1315
1316         bglFlush();
1317         glReadBuffer(GL_BACK);
1318         glDrawBuffer(GL_BACK);
1319         persp(PERSP_VIEW);
1320
1321         if(G.qual != LR_SHIFTKEY)
1322                 LOOP_PARTICLES(i,pa){
1323                         if(pa->flag & PARS_HIDE) continue;
1324                         LOOP_KEYS(k,key){
1325                                 if(key->flag & PEK_SELECT) {
1326                                         key->flag &= ~PEK_SELECT;
1327                                         pa->flag |= PARS_EDIT_RECALC;
1328                                 }
1329                         }
1330                 }
1331
1332         getmouseco_areawin(mval);
1333
1334         data.mval=mval;
1335         data.rad=75.0f;
1336         data.rect=0;
1337         data.select=0;
1338
1339         for_mouse_hit_keys(1,psys,toggle_key_select,&data);
1340
1341         PE_update_selection(ob, 1);
1342
1343         rightmouse_transform();
1344
1345         allqueue(REDRAWVIEW3D, 1);
1346 }
1347 void PE_select_root()
1348 {
1349         Object *ob=OBACT;
1350         ParticleSystem *psys = PE_get_current(ob);
1351
1352         if(!PE_can_edit(psys)) return;
1353
1354         PE_foreach_element(psys,select_root,NULL);
1355         BIF_undo_push("Select first");
1356 }
1357 void PE_select_tip()
1358 {
1359         Object *ob=OBACT;
1360         ParticleSystem *psys = PE_get_current(ob);
1361
1362         if(!PE_can_edit(psys)) return;
1363
1364         PE_foreach_element(psys,select_tip,NULL);
1365         BIF_undo_push("Select last");
1366 }
1367 void PE_select_linked(void)
1368 {
1369         struct { short *mval; float rad; rcti* rect; int select; } data;
1370         Object *ob = OBACT;
1371         ParticleSystem *psys = PE_get_current(ob);
1372         short mval[2];
1373
1374         if(!PE_can_edit(psys)) return;
1375
1376         getmouseco_areawin(mval);
1377
1378         data.mval=mval;
1379         data.rad=75.0f;
1380         data.rect=0;
1381         data.select=(G.qual != LR_SHIFTKEY);
1382
1383         for_mouse_hit_keys(1,psys,select_keys,&data);
1384
1385         PE_update_selection(ob, 1);
1386
1387         BIF_undo_push("Select linked keys");
1388
1389         allqueue(REDRAWVIEW3D, 1);
1390         return;
1391 }
1392 void PE_borderselect(void)
1393 {
1394         struct { short *mval; float rad; rcti* rect; int select; } data;
1395         Object *ob = OBACT;
1396         ParticleSystem *psys = PE_get_current(ob);
1397         rcti rect;
1398         int val;
1399
1400         if(!PE_can_edit(psys)) return;
1401
1402         setlinestyle(2);
1403         val= get_border(&rect, 3);
1404         setlinestyle(0);
1405         
1406         if(val==0) return;
1407
1408         data.mval=0;
1409         data.rect=&rect;
1410         data.select=(val==LEFTMOUSE);
1411
1412         for_mouse_hit_keys(0,psys,select_key,&data);
1413
1414         PE_update_selection(ob, 1);
1415
1416         BIF_undo_push("Select keys");
1417
1418         allqueue(REDRAWVIEW3D, 1);
1419         return;
1420 }
1421 void PE_selectionCB(short selecting, Object *editobj, short *mval, float rad)
1422 {
1423         struct { short *mval; float rad; rcti* rect; int select; } data;
1424         ParticleSystem *psys = PE_get_current(OBACT);
1425
1426         if(!PE_can_edit(psys)) return;
1427
1428         data.mval=mval;
1429         data.rad=rad;
1430         data.rect=0;
1431         data.select=(selecting==LEFTMOUSE);
1432
1433         for_mouse_hit_keys(0,psys,select_key,&data);
1434
1435         draw_sel_circle(0, 0, 0, 0, 0); /* signal */
1436         force_draw(0);
1437 }
1438 void PE_do_lasso_select(short mcords[][2], short moves, short select)
1439 {
1440         Object *ob = OBACT;
1441         ParticleSystem *psys = PE_get_current(ob);
1442         ParticleSystemModifierData *psmd;
1443         ParticleEdit *edit;
1444         ParticleData *pa;
1445         ParticleEditKey *key;
1446         float co[3], mat[4][4];
1447         short vertco[2];
1448         int i, k, totpart;
1449
1450         if(!PE_can_edit(psys)) return;
1451
1452         psmd= psys_get_modifier(ob, psys);
1453         edit=psys->edit;
1454         totpart=psys->totpart;
1455
1456         LOOP_PARTICLES(i,pa){
1457                 if(pa->flag & PARS_HIDE) continue;
1458
1459                 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1460
1461                 if(G.scene->selectmode==SCE_SELECT_POINT){
1462                         LOOP_KEYS(k,key){
1463                                 VECCOPY(co, key->co);
1464                                 Mat4MulVecfl(mat, co);
1465                                 project_short(co,vertco);
1466                                 if((vertco[0] != IS_CLIPPED) && lasso_inside(mcords,moves,vertco[0],vertco[1])){
1467                                         if(select && !(key->flag & PEK_SELECT)) {
1468                                                 key->flag|=PEK_SELECT;
1469                                                 pa->flag |= PARS_EDIT_RECALC;
1470                                         }
1471                                         else if(key->flag & PEK_SELECT) {
1472                                                 key->flag&=~PEK_SELECT;
1473                                                 pa->flag |= PARS_EDIT_RECALC;
1474                                         }
1475                                 }
1476                         }
1477                 }
1478                 else if(G.scene->selectmode==SCE_SELECT_END){
1479                         key = edit->keys[i] + pa->totkey - 1;
1480
1481                         VECCOPY(co, key->co);
1482                         Mat4MulVecfl(mat, co);
1483                         project_short(co,vertco);
1484                         if((vertco[0] != IS_CLIPPED) && lasso_inside(mcords,moves,vertco[0],vertco[1])){
1485                                 if(select && !(key->flag & PEK_SELECT)) {
1486                                         key->flag|=PEK_SELECT;
1487                                         pa->flag |= PARS_EDIT_RECALC;
1488                                 }
1489                                 else if(key->flag & PEK_SELECT) {
1490                                         key->flag&=~PEK_SELECT;
1491                                         pa->flag |= PARS_EDIT_RECALC;
1492                                 }
1493                         }
1494                 }
1495         }
1496
1497         PE_update_selection(ob, 1);
1498
1499         BIF_undo_push("Lasso select particles");
1500
1501         allqueue(REDRAWVIEW3D, 1);
1502 }
1503 void PE_hide(int mode)
1504 {
1505         ParticleSystem *psys = PE_get_current(OBACT);
1506         ParticleEdit *edit;
1507         ParticleData *pa;
1508         int i,totpart;
1509
1510         if(!PE_can_edit(psys)) return;
1511
1512         edit = psys->edit;
1513         totpart = psys->totpart;
1514         
1515         if(mode == 0){ /* reveal all particles */
1516                 LOOP_PARTICLES(i,pa){
1517                         pa->flag &= ~PARS_HIDE;
1518                 }
1519         }
1520         else if(mode == 1){ /* hide unselected particles */
1521                 LOOP_PARTICLES(i,pa)
1522                         if(particle_is_selected(psys, pa))
1523                                 pa->flag |= PARS_HIDE;
1524         }
1525         else{ /* hide selected particles */
1526                 LOOP_PARTICLES(i,pa)
1527                         if(particle_is_selected(psys, pa))
1528                                 pa->flag |= PARS_HIDE;
1529         }
1530
1531         BIF_undo_push("(Un)hide elements");
1532         
1533         allqueue(REDRAWVIEW3D, 1);
1534 }
1535 void PE_select_less(void)
1536 {
1537         ParticleSystem *psys = PE_get_current(OBACT);
1538
1539         if(!PE_can_edit(psys)) return;
1540
1541         PE_foreach_element(psys,select_less_keys,NULL);
1542         
1543         BIF_undo_push("Select less");
1544         allqueue(REDRAWVIEW3D, 1);
1545 }
1546 void PE_select_more(void)
1547 {
1548         ParticleSystem *psys = PE_get_current(OBACT);
1549
1550         if(!PE_can_edit(psys)) return;
1551
1552         PE_foreach_element(psys,select_more_keys,NULL);
1553         
1554         BIF_undo_push("Select more");
1555         allqueue(REDRAWVIEW3D, 1);
1556 }
1557 /************************************************/
1558 /*                      Edit Rekey                                                      */
1559 /************************************************/
1560 static void rekey_element(ParticleSystem *psys, int index, void *userData)
1561 {
1562         struct { Object *ob; float dval; } *data = userData;
1563         ParticleData *pa = psys->particles + index;
1564         ParticleEdit *edit = psys->edit;
1565         ParticleEditSettings *pset = PE_settings();
1566         ParticleKey state;
1567         HairKey *key, *new_keys;
1568         ParticleEditKey *ekey;
1569         float dval, sta, end;
1570         int k;
1571
1572         pa->flag |= PARS_REKEY;
1573
1574         key = new_keys = MEM_callocN(pset->totrekey * sizeof(HairKey),"Hair re-key keys");
1575
1576         /* root and tip stay the same */
1577         VECCOPY(key->co, pa->hair->co);
1578         VECCOPY((key + pset->totrekey - 1)->co, (pa->hair + pa->totkey - 1)->co);
1579
1580         sta = key->time = pa->hair->time;
1581         end = (key + pset->totrekey - 1)->time = (pa->hair + pa->totkey - 1)->time;
1582         dval = (end - sta) / (float)(pset->totrekey - 1);
1583
1584         /* interpolate new keys from old ones */
1585         for(k=1,key++; k<pset->totrekey-1; k++,key++) {
1586                 state.time = (float)k / (float)(pset->totrekey-1);
1587                 psys_get_particle_on_path(data->ob, psys, index, &state, 0);
1588                 VECCOPY(key->co, state.co);
1589                 key->time = sta + k * dval;
1590         }
1591
1592         /* replace keys */
1593         if(pa->hair)
1594                 MEM_freeN(pa->hair);
1595         pa->hair = new_keys;
1596
1597         pa->totkey=pset->totrekey;
1598
1599         if(edit->keys[index])
1600                 MEM_freeN(edit->keys[index]);
1601         ekey = edit->keys[index] = MEM_callocN(pa->totkey * sizeof(ParticleEditKey),"Hair re-key edit keys");
1602                 
1603         for(k=0, key=pa->hair; k<pa->totkey; k++, key++, ekey++) {
1604                 ekey->co = key->co;
1605                 ekey->time = &key->time;
1606         }
1607
1608         pa->flag &= ~PARS_REKEY;
1609         pa->flag |= PARS_EDIT_RECALC;
1610 }
1611 void PE_rekey(void)
1612 {
1613         Object *ob=OBACT;
1614         ParticleSystem *psys = PE_get_current(ob);
1615         ParticleEditSettings *pset = PE_settings();
1616         struct { Object *ob; float dval; } data;
1617
1618         if(!PE_can_edit(psys)) return;
1619
1620         data.ob = ob;
1621         data.dval = 1.0f / (float)(pset->totrekey-1);
1622
1623         foreach_selected_element(psys,rekey_element,&data);
1624         
1625         psys->edit->totkeys = psys_count_keys(psys);
1626
1627         recalc_lengths(psys);
1628         
1629         PE_update_object(ob, 1);
1630
1631         BIF_undo_push("Re-key particles");
1632 }
1633 static void rekey_element_to_time(int index, float path_time)
1634 {
1635         Object *ob = OBACT;
1636         ParticleSystem *psys = PE_get_current(ob);
1637         ParticleEdit *edit=0;
1638         ParticleData *pa;
1639         ParticleKey state;
1640         HairKey *new_keys, *key;
1641         ParticleEditKey *ekey;
1642         int k;
1643
1644         if(psys==0) return;
1645
1646         edit = psys->edit;
1647
1648         pa = psys->particles + index;
1649
1650         pa->flag |= PARS_REKEY;
1651
1652         key = new_keys = MEM_dupallocN(pa->hair);
1653         
1654         /* interpolate new keys from old ones (roots stay the same) */
1655         for(k=1, key++; k < pa->totkey; k++, key++) {
1656                 state.time = path_time * (float)k / (float)(pa->totkey-1);
1657                 psys_get_particle_on_path(ob, psys, index, &state, 0);
1658                 VECCOPY(key->co, state.co);
1659         }
1660
1661         /* replace hair keys */
1662         if(pa->hair)
1663                 MEM_freeN(pa->hair);
1664         pa->hair = new_keys;
1665
1666         /* update edit pointers */
1667         for(k=0, key=pa->hair, ekey=edit->keys[index]; k<pa->totkey; k++, key++, ekey++) {
1668                 ekey->co = key->co;
1669                 ekey->time = &key->time;
1670         }
1671
1672         pa->flag &= ~PARS_REKEY;
1673 }
1674 static int remove_tagged_elements(Object *ob, ParticleSystem *psys)
1675 {
1676         ParticleEdit *edit = psys->edit;
1677         ParticleEditSettings *pset = PE_settings();
1678         ParticleData *pa, *npa=0, *new_pars=0;
1679         ParticleEditKey **key, **nkey=0, **new_keys=0;
1680         ParticleSystemModifierData *psmd;
1681         int i, totpart, new_totpart = psys->totpart, removed = 0;
1682
1683         if(pset->flag & PE_X_MIRROR) {
1684                 /* mirror tags */
1685                 psmd = psys_get_modifier(ob, psys);
1686                 totpart = psys->totpart;
1687
1688                 LOOP_PARTICLES(i,pa)
1689                         if(pa->flag & PARS_TAG)
1690                                 PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
1691         }
1692
1693         for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++) {
1694                 if(pa->flag & PARS_TAG) {
1695                         new_totpart--;
1696                         removed++;
1697                 }
1698         }
1699
1700         if(new_totpart != psys->totpart) {
1701                 if(new_totpart) {
1702                         npa = new_pars = MEM_callocN(new_totpart * sizeof(ParticleData), "ParticleData array");
1703                         nkey = new_keys = MEM_callocN(new_totpart * sizeof(ParticleEditKey *), "ParticleEditKey array");
1704                 }
1705
1706                 pa = psys->particles;
1707                 key = edit->keys;
1708                 for(i=0; i<psys->totpart; i++, pa++, key++) {
1709                         if(pa->flag & PARS_TAG) {
1710                                 if(*key)
1711                                         MEM_freeN(*key);
1712                                 if(pa->hair)
1713                                         MEM_freeN(pa->hair);
1714                         }
1715                         else {
1716                                 memcpy(npa, pa, sizeof(ParticleData));
1717                                 memcpy(nkey, key, sizeof(ParticleEditKey*));
1718                                 npa++;
1719                                 nkey++;
1720                         }
1721                 }
1722
1723                 if(psys->particles) MEM_freeN(psys->particles);
1724                 psys->particles = new_pars;
1725
1726                 if(edit->keys) MEM_freeN(edit->keys);
1727                 edit->keys = new_keys;
1728
1729                 if(edit->mirror_cache) {
1730                         MEM_freeN(edit->mirror_cache);
1731                         edit->mirror_cache = NULL;
1732                 }
1733
1734                 psys->totpart = new_totpart;
1735
1736                 edit->totkeys = psys_count_keys(psys);
1737         }
1738
1739         return removed;
1740 }
1741 static void remove_tagged_keys(Object *ob, ParticleSystem *psys)
1742 {
1743         ParticleEdit *edit = psys->edit;
1744         ParticleEditSettings *pset = PE_settings();
1745         ParticleData *pa;
1746         HairKey *key, *nkey, *new_keys=0;
1747         ParticleEditKey *ekey;
1748         ParticleSystemModifierData *psmd;
1749         int i, k, totpart = psys->totpart;
1750         short new_totkey;
1751
1752         if(pset->flag & PE_X_MIRROR) {
1753                 /* mirror key tags */
1754                 psmd = psys_get_modifier(ob, psys);
1755
1756                 LOOP_PARTICLES(i,pa) {
1757                         LOOP_KEYS(k,ekey) {
1758                                 if(ekey->flag & PEK_TAG) {
1759                                         PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
1760                                         break;
1761                                 }
1762                         }
1763                 }
1764         }
1765
1766         LOOP_PARTICLES(i,pa) {
1767                 new_totkey = pa->totkey;
1768                 LOOP_KEYS(k,ekey) {
1769                         if(ekey->flag & PEK_TAG)
1770                                 new_totkey--;
1771                 }
1772                 /* we can't have elements with less than two keys*/
1773                 if(new_totkey < 2)
1774                         pa->flag |= PARS_TAG;
1775         }
1776         remove_tagged_elements(ob, psys);
1777
1778         totpart = psys->totpart;
1779
1780         LOOP_PARTICLES(i,pa) {
1781                 new_totkey = pa->totkey;
1782                 LOOP_KEYS(k,ekey) {
1783                         if(ekey->flag & PEK_TAG)
1784                                 new_totkey--;
1785                 }
1786                 if(new_totkey != pa->totkey) {
1787                         key = pa->hair;
1788                         nkey = new_keys = MEM_callocN(new_totkey*sizeof(HairKey), "HairKeys");
1789
1790                         for(k=0, ekey=edit->keys[i]; k<new_totkey; k++, key++, nkey++, ekey++) {
1791                                 while(ekey->flag & PEK_TAG && key < pa->hair + pa->totkey) {
1792                                         key++;
1793                                         ekey++;
1794                                 }
1795
1796                                 if(key < pa->hair + pa->totkey) {
1797                                         VECCOPY(nkey->co, key->co);
1798                                         nkey->time = key->time;
1799                                         nkey->weight = key->weight;
1800                                 }
1801                         }
1802                         if(pa->hair)
1803                                 MEM_freeN(pa->hair);
1804                         
1805                         pa->hair = new_keys;
1806
1807                         pa->totkey=new_totkey;
1808
1809                         if(edit->keys[i])
1810                                 MEM_freeN(edit->keys[i]);
1811                         ekey = edit->keys[i] = MEM_callocN(new_totkey*sizeof(ParticleEditKey), "particle edit keys");
1812
1813                         for(k=0, key=pa->hair; k<pa->totkey; k++, key++, ekey++) {
1814                                 ekey->co = key->co;
1815                                 ekey->time = &key->time;
1816                         }
1817                 }
1818         }
1819
1820         edit->totkeys = psys_count_keys(psys);
1821 }
1822 /* works like normal edit mode subdivide, inserts keys between neighbouring selected keys */
1823 static void subdivide_element(ParticleSystem *psys, int index, void *userData)
1824 {
1825         struct { Object *ob; } *data = userData;
1826         ParticleEdit *edit = psys->edit;
1827         ParticleData *pa = psys->particles + index;
1828         
1829         ParticleKey state;
1830         HairKey *key, *nkey, *new_keys;
1831         ParticleEditKey *ekey, *nekey, *new_ekeys;
1832
1833         int k;
1834         short totnewkey=0;
1835         float endtime;
1836
1837         for(k=0, ekey=edit->keys[index]; k<pa->totkey-1; k++,ekey++){
1838                 if(ekey->flag&PEK_SELECT && (ekey+1)->flag&PEK_SELECT)
1839                         totnewkey++;
1840         }
1841
1842         if(totnewkey==0) return;
1843
1844         pa->flag |= PARS_REKEY;
1845
1846         nkey = new_keys = MEM_callocN((pa->totkey+totnewkey)*(sizeof(HairKey)),"Hair subdivide keys");
1847         nekey = new_ekeys = MEM_callocN((pa->totkey+totnewkey)*(sizeof(ParticleEditKey)),"Hair subdivide edit keys");
1848         endtime = pa->hair[pa->totkey-1].time;
1849
1850         for(k=0, key=pa->hair, ekey=edit->keys[index]; k<pa->totkey-1; k++, key++, ekey++){
1851
1852                 memcpy(nkey,key,sizeof(HairKey));
1853                 memcpy(nekey,ekey,sizeof(ParticleEditKey));
1854
1855                 nekey->co = nkey->co;
1856                 nekey->time = &nkey->time;
1857
1858                 nkey++;
1859                 nekey++;
1860
1861                 if(ekey->flag & PEK_SELECT && (ekey+1)->flag & PEK_SELECT){
1862                         nkey->time= (key->time + (key+1)->time)*0.5f;
1863                         state.time = (endtime != 0.0f)? nkey->time/endtime: 0.0f;
1864                         psys_get_particle_on_path(data->ob, psys, index, &state, 0);
1865                         VECCOPY(nkey->co, state.co);
1866
1867                         nekey->co= nkey->co;
1868                         nekey->time= &nkey->time;
1869                         nekey->flag |= PEK_SELECT;
1870
1871                         nekey++;
1872                         nkey++;
1873                 }
1874         }
1875         /*tip still not copied*/
1876         memcpy(nkey,key,sizeof(HairKey));
1877         memcpy(nekey,ekey,sizeof(ParticleEditKey));
1878
1879         nekey->co = nkey->co;
1880         nekey->time = &nkey->time;
1881
1882         if(pa->hair)
1883                 MEM_freeN(pa->hair);
1884         pa->hair = new_keys;
1885
1886         if(edit->keys[index])
1887                 MEM_freeN(edit->keys[index]);
1888
1889         edit->keys[index] = new_ekeys;
1890
1891         pa->totkey += totnewkey;
1892         pa->flag |= PARS_EDIT_RECALC;
1893         pa->flag &= ~PARS_REKEY;
1894 }
1895 void PE_subdivide(void)
1896 {
1897         Object *ob = OBACT;
1898         ParticleSystem *psys = PE_get_current(ob);
1899         struct { Object *ob; } data;
1900
1901         if(!PE_can_edit(psys)) return;
1902
1903         data.ob= ob;
1904         PE_foreach_element(psys,subdivide_element,&data);
1905         
1906         psys->edit->totkeys = psys_count_keys(psys);
1907         
1908         recalc_lengths(psys);
1909         PE_recalc_world_cos(ob, psys);
1910
1911         PE_update_object(ob, 1);
1912         
1913         BIF_undo_push("Subdivide hair(s)");
1914 }
1915 void PE_remove_doubles(void)
1916 {
1917         Object *ob=OBACT;
1918         ParticleSystem *psys=PE_get_current(ob);
1919         ParticleEditSettings *pset=PE_settings();
1920         ParticleData *pa;
1921         ParticleEdit *edit;
1922         ParticleSystemModifierData *psmd;
1923         KDTree *tree;
1924         KDTreeNearest nearest[10];
1925         float mat[4][4], co[3];
1926         int i, n, totn, removed, totpart, flag, totremoved;
1927
1928         if(!PE_can_edit(psys)) return;
1929
1930         edit= psys->edit;
1931         psmd= psys_get_modifier(ob, psys);
1932         totremoved= 0;
1933
1934         do {
1935                 removed= 0;
1936
1937                 totpart= psys->totpart;
1938                 tree=BLI_kdtree_new(totpart);
1939                         
1940                 /* insert particles into kd tree */
1941                 LOOP_PARTICLES(i,pa) {
1942                         if(particle_is_selected(psys, pa)) {
1943                                 psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, mat);
1944                                 VECCOPY(co, pa->hair[0].co);
1945                                 Mat4MulVecfl(mat, co);
1946                                 BLI_kdtree_insert(tree, i, co, NULL);
1947                         }
1948                 }
1949
1950                 BLI_kdtree_balance(tree);
1951
1952                 /* tag particles to be removed */
1953                 LOOP_PARTICLES(i,pa) {
1954                         if(particle_is_selected(psys, pa)) {
1955                                 psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, mat);
1956                                 VECCOPY(co, pa->hair[0].co);
1957                                 Mat4MulVecfl(mat, co);
1958
1959                                 totn= BLI_kdtree_find_n_nearest(tree,10,co,NULL,nearest);
1960
1961                                 for(n=0; n<totn; n++) {
1962                                         /* this needs a custom threshold still */
1963                                         if(nearest[n].index > i && nearest[n].dist < 0.0002f) {
1964                                                 if(!(pa->flag & PARS_TAG)) {
1965                                                         pa->flag |= PARS_TAG;
1966                                                         removed++;
1967                                                 }
1968                                         }
1969                                 }
1970                         }
1971                 }
1972
1973                 BLI_kdtree_free(tree);
1974
1975                 /* remove tagged particles - don't do mirror here! */
1976                 flag= pset->flag;
1977                 pset->flag &= ~PE_X_MIRROR;
1978                 remove_tagged_elements(ob, psys);
1979                 pset->flag= flag;
1980                 totremoved += removed;
1981         } while(removed);
1982
1983         if(totremoved)
1984                 notice("Removed: %d", totremoved);
1985
1986         PE_recalc_world_cos(ob, psys);
1987         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1988         allqueue(REDRAWVIEW3D, 1);
1989         BIF_undo_push("Remove double particles");
1990 }
1991
1992 /************************************************/
1993 /*                      Edit Brushes                                            */
1994 /************************************************/
1995 static void brush_comb(ParticleSystem *psys, float mat[][4], float imat[][4], int pa_index, int key_index, void *userData)
1996 {
1997         struct {Object *ob; short *mval; float rad; rcti* rect; float dist; float *dvec; float combfac;} *data = userData;
1998         ParticleData *pa= &psys->particles[pa_index];
1999         ParticleEditSettings *pset= PE_settings();
2000         HairKey *key = pa->hair + key_index;
2001         float cvec[3], fac;
2002
2003         if(pset->flag & PE_LOCK_FIRST && key_index == 0) return;
2004
2005         fac = (float)pow((double)(1.0f - data->dist / data->rad), (double)data->combfac);
2006
2007         VECCOPY(cvec,data->dvec);
2008         Mat4Mul3Vecfl(imat,cvec);
2009         VecMulf(cvec, fac);
2010         VECADD(key->co, key->co, cvec);
2011
2012         pa->flag |= PARS_EDIT_RECALC;
2013 }
2014 static void brush_cut(ParticleSystem *psys, int index, void *userData)
2015 {
2016         struct { short *mval; float rad; rcti* rect; int selected; float cutfac;} *data = userData;
2017         ParticleData *pa= &psys->particles[index];
2018         ParticleCacheKey *key = psys->pathcache[index];
2019         float rad2, cut_time = 1.0;
2020         float x0, x1, v0, v1, o0, o1, xo0, xo1, d, dv;
2021         int k, cut, keys = (int)pow(2.0, (double)psys->part->draw_step);
2022         short vertco[2];
2023
2024         /* blunt scissors */
2025         if(BLI_frand() > data->cutfac) return;
2026
2027         rad2 = data->rad * data->rad;
2028
2029         cut=0;
2030
2031         project_short_noclip(key->co, vertco);
2032         x0 = (float)vertco[0];
2033         x1 = (float)vertco[1];
2034
2035         o0 = (float)data->mval[0];
2036         o1 = (float)data->mval[1];
2037         
2038         xo0 = x0 - o0;
2039         xo1 = x1 - o1;
2040
2041         /* check if root is inside circle */
2042         if(xo0*xo0 + xo1*xo1 < rad2) {
2043                 cut_time = -1.0f;
2044                 cut = 1;
2045         }
2046         else {
2047                 /* calculate path time closest to root that was inside the circle */
2048                 for(k=1, key++; k<=keys; k++, key++){
2049                         project_short_noclip(key->co, vertco);
2050
2051                         v0 = (float)vertco[0] - x0;
2052                         v1 = (float)vertco[1] - x1;
2053
2054                         dv = v0*v0 + v1*v1;
2055
2056                         d = (v0*xo1 - v1*xo0);
2057                         
2058                         d = dv * rad2 - d*d;
2059
2060                         if(d > 0.0f) {
2061                                 d = sqrt(d);
2062
2063                                 cut_time = -(v0*xo0 + v1*xo1 + d);
2064
2065                                 if(cut_time > 0.0f) {
2066                                         cut_time /= dv;
2067
2068                                         if(cut_time < 1.0f) {
2069                                                 cut_time += (float)(k-1);
2070                                                 cut_time /= (float)keys;
2071                                                 cut = 1;
2072                                                 break;
2073                                         }
2074                                 }
2075                         }
2076
2077                         x0 = (float)vertco[0];
2078                         x1 = (float)vertco[1];
2079
2080                         xo0 = x0 - o0;
2081                         xo1 = x1 - o1;
2082                 }
2083         }
2084
2085         if(cut) {
2086                 if(cut_time < 0.0f) {
2087                         pa->flag |= PARS_TAG;
2088                 }
2089                 else {
2090                         rekey_element_to_time(index, cut_time);
2091                         pa->flag |= PARS_EDIT_RECALC;
2092                 }
2093         }
2094 }
2095 static void brush_length(ParticleSystem *psys, int index, void *userData)
2096 {
2097         struct { short *mval; float rad; rcti* rect; float dist; float growfac; } *data = userData;
2098         ParticleData *pa = &psys->particles[index];
2099         HairKey *key;
2100         float dvec[3],pvec[3];
2101         int k;
2102
2103         key = pa->hair;
2104         VECCOPY(pvec,key->co);
2105
2106         for(k=1, key++; k<pa->totkey; k++,key++){
2107                 VECSUB(dvec,key->co,pvec);
2108                 VECCOPY(pvec,key->co);
2109                 VecMulf(dvec,data->growfac);
2110                 VECADD(key->co,(key-1)->co,dvec);
2111         }
2112
2113         pa->flag |= PARS_EDIT_RECALC;
2114 }
2115 static void brush_puff(ParticleSystem *psys, int index, void *userData)
2116 {
2117         struct { short *mval; float rad; rcti* rect; float dist;
2118                 Object *ob; DerivedMesh *dm; float pufffac; int invert; } *data = userData;
2119         ParticleData *pa = &psys->particles[index];
2120         ParticleEdit *edit = psys->edit;
2121         HairKey *key;
2122         float mat[4][4], imat[4][4];
2123         float lastco[3], rootco[3], co[3], nor[3], kco[3], dco[3], fac, length;
2124         int k;
2125
2126         psys_mat_hair_to_global(data->ob, data->dm, psys->part->from, pa, mat);
2127         Mat4Invert(imat,mat);
2128
2129         /* find root coordinate and normal on emitter */
2130         key = pa->hair;
2131         VECCOPY(co, key->co);
2132         Mat4MulVecfl(mat, co);
2133
2134         index= BLI_kdtree_find_nearest(edit->emitter_field, co, NULL, NULL);
2135         if(index == -1) return;
2136
2137         VECCOPY(rootco, co);
2138         VecCopyf(nor, &psys->edit->emitter_cosnos[index*6+3]);
2139         Normalize(nor);
2140         length= 0.0f;
2141
2142         fac= (float)pow((double)(1.0f - data->dist / data->rad), (double)data->pufffac);
2143         fac *= 0.025f;
2144         if(data->invert)
2145                 fac= -fac;
2146
2147         for(k=1, key++; k<pa->totkey; k++, key++){
2148                 /* compute position as if hair was standing up straight */
2149                 VECCOPY(lastco, co);
2150                 VECCOPY(co, key->co);
2151                 Mat4MulVecfl(mat, co);
2152                 length += VecLenf(lastco, co);
2153
2154                 VECADDFAC(kco, rootco, nor, length);
2155
2156                 /* blend between the current and straight position */
2157                 VECSUB(dco, kco, co);
2158                 VECADDFAC(co, co, dco, fac);
2159
2160                 VECCOPY(key->co, co);
2161                 Mat4MulVecfl(imat, key->co);
2162         }
2163
2164         pa->flag |= PARS_EDIT_RECALC;
2165 }
2166 static void brush_smooth_get(ParticleSystem *psys, float mat[][4], float imat[][4], int pa_index, int key_index, void *userData)
2167 {
2168         struct { Object *ob; short *mval; float rad; rcti* rect; float dist; float vec[3]; int tot; float smoothfac;} *data = userData;
2169         ParticleData *pa= &psys->particles[pa_index];
2170         HairKey *key = pa->hair + key_index;
2171         
2172         if(key_index){
2173                 float dvec[3];
2174
2175                 VecSubf(dvec,key->co,(key-1)->co);
2176                 Mat4Mul3Vecfl(mat,dvec);
2177                 VECADD(data->vec,data->vec,dvec);
2178                 data->tot++;
2179         }
2180 }
2181 static void brush_smooth_do(ParticleSystem *psys, float mat[][4], float imat[][4], int pa_index, int key_index, void *userData)
2182 {
2183         struct { Object *ob; short *mval; float rad; rcti* rect; float dist; float vec[3]; int tot; float smoothfac;} *data = userData;
2184         ParticleData *pa= &psys->particles[pa_index];
2185         HairKey *key = pa->hair + key_index;
2186         float vec[3], dvec[3];
2187         
2188         if(key_index){
2189                 VECCOPY(vec,data->vec);
2190                 Mat4Mul3Vecfl(imat,vec);
2191
2192                 VecSubf(dvec,key->co,(key-1)->co);
2193
2194                 VECSUB(dvec,vec,dvec);
2195                 VecMulf(dvec,data->smoothfac);
2196                 
2197                 VECADD(key->co,key->co,dvec);
2198         }
2199
2200         pa->flag |= PARS_EDIT_RECALC;
2201 }
2202 #define EXPERIMENTAL_DEFORM_ONLY_PAINTING 1
2203 static void brush_add(Object *ob, ParticleSystem *psys, short *mval, short number)
2204 {
2205         ParticleData *add_pars = MEM_callocN(number*sizeof(ParticleData),"ParticleData add");
2206         ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys);
2207         ParticleEditSettings *pset= PE_settings();
2208         ParticleEdit *edit = psys->edit;
2209         int i, k, n = 0, totpart = psys->totpart;
2210         short dmx = 0, dmy = 0;
2211         short mx = mval[0] - curarea->winx / 2, my = mval[1] - curarea->winy / 2;
2212         float co1[3], co2[3], vec[4], min_d, imat[4][4];
2213         float framestep, timestep = psys_get_timestep(psys->part);
2214         short size = pset->brush[PE_BRUSH_ADD].size;
2215         short size2 = size*size;
2216 #if EXPERIMENTAL_DEFORM_ONLY_PAINTING
2217         DerivedMesh *dm=0;
2218 #endif
2219         Mat4Invert(imat,ob->obmat);
2220
2221         BLI_srandom(psys->seed+mval[0]+mval[1]);
2222         
2223         /* painting onto the deformed mesh, could be an option? */
2224 #if EXPERIMENTAL_DEFORM_ONLY_PAINTING
2225         if (psmd->dm->deformedOnly)
2226                 dm = psmd->dm;
2227         else
2228                 dm = mesh_get_derived_deform(ob, CD_MASK_BAREMESH);
2229 #endif
2230         for(i=0; i<number; i++){
2231                 if(number>1){
2232                         dmx=dmy=size;
2233                         while(dmx*dmx+dmy*dmy>size2){
2234                                 dmx=(short)((2.0f*BLI_frand()-1.0f)*size);
2235                                 dmy=(short)((2.0f*BLI_frand()-1.0f)*size);
2236                         }
2237                 }
2238
2239                 /* create intersection coordinates in view Z direction at mouse coordinates */
2240                 /* Thanks to who ever wrote the "Mouse Location 3D Space" tutorial in "Blender 3D: Blending Into Python/Cookbook". */
2241                 if(G.vd->persp){
2242                         vec[0]= (2.0f*(mx+dmx)/curarea->winx);
2243                         vec[1]= (2.0f*(my+dmy)/curarea->winy);
2244                         vec[2]= -1.0f;
2245                         vec[3]= 1.0f;
2246
2247                         Mat4MulVec4fl(G.vd->persinv, vec);
2248                         VecMulf(vec, 1.0f/vec[3]);
2249
2250                         VECCOPY(co1, G.vd->viewinv[3]);
2251                         VECSUB(vec, vec, co1);
2252                         Normalize(vec);
2253
2254                         VECADDFAC(co1, G.vd->viewinv[3], vec, G.vd->near);
2255                         VECADDFAC(co2, G.vd->viewinv[3], vec, G.vd->far);
2256                 }
2257                 else {
2258                         vec[0] = 2.0f*(mx+dmx)/curarea->winx;
2259                         vec[1] = 2.0f*(my+dmy)/curarea->winy;
2260                         vec[2] = 0.0f;
2261                         vec[3] = 1.0f;
2262
2263                         Mat4MulVec4fl(G.vd->persinv,vec);
2264
2265                         VECADDFAC(co1,vec,G.vd->viewinv[2],1000.0f);
2266                         VECADDFAC(co2,vec,G.vd->viewinv[2],-1000.0f);
2267                 }
2268
2269                 Mat4MulVecfl(imat,co1);
2270                 Mat4MulVecfl(imat,co2);
2271                 min_d=2.0;
2272                 
2273                 /* warning, returns the derived mesh face */
2274 #if EXPERIMENTAL_DEFORM_ONLY_PAINTING
2275                 if(psys_intersect_dm(ob,dm,0,co1,co2,&min_d,&add_pars[n].num,add_pars[n].fuv,0,0,0,0)) {
2276                         add_pars[n].num_dmcache= psys_particle_dm_face_lookup(ob,psmd->dm,add_pars[n].num,add_pars[n].fuv,NULL);
2277                         n++;
2278                 }
2279 #else
2280 #if 0
2281                 if (psmd->dm->deformedOnly) {
2282                         if(psys_intersect_dm(ob,psmd->dm,0,co1,co2,&min_d,&add_pars[n].num,add_pars[n].fuv,0,0,0,0)){
2283                                 n++;
2284                         }
2285                 } else {
2286                         /* we need to test against the cage mesh, because 1) its faster and 2) then we can avoid converting the fuv back which is not simple */
2287                         if(psys_intersect_dm(ob,psmd->dm,0,co1,co2,&min_d,&add_pars[n].num,add_pars[n].fuv,0,0,0,0)){
2288                                 MFace *mface;
2289                                 float fuv_mod[3] = {0.0, 0.0, 0.0};
2290                                 OrigSpaceFace *osface;
2291                                 
2292                                 mface= psmd->dm->getFaceData(psmd->dm,add_pars[n].num,CD_MFACE);
2293                                 osface= psmd->dm->getFaceData(psmd->dm, add_pars[n].num, CD_ORIGSPACE);
2294                                 
2295                                 add_pars[n].fuv[2]=0.0;
2296                                 
2297                                 /* use the original index for num and the derived index for num_dmcache */
2298                                 add_pars[n].num_dmcache = add_pars[n].num;
2299                                 add_pars[n].num = *(int *)psmd->dm->getFaceData(psmd->dm, add_pars[n].num, CD_ORIGINDEX);
2300                                 
2301                                 /* This is totally unaceptable code (fakeing mesh dara) but changing the target function isnt really nice either, do this temporarily */
2302                                 if (1) { /* Evilness*/
2303                                         MFace mface_fake;
2304                                         MVert mvert_fake[4];
2305                                         //int test1,test2;
2306                                         //test1 = add_pars[n].num_dmcache;
2307                                         //test2 = add_pars[n].num;
2308                                         
2309                                         mvert_fake[0].co[2] = mvert_fake[1].co[2] = mvert_fake[2].co[2] = mvert_fake[3].co[2] = 0.0;
2310                                         
2311                                         mface_fake.v1 = 0;
2312                                         mface_fake.v2 = 1;
2313                                         mface_fake.v3 = 2;
2314                                         
2315                                         if (mface->v4) {
2316                                                 mface_fake.v4 = 3;
2317                                         } else {
2318                                                 mface_fake.v4 = 0;
2319                                         }
2320                                         
2321                                         Vec2Copyf(mvert_fake[0].co, osface->uv[0]);
2322                                         Vec2Copyf(mvert_fake[1].co, osface->uv[1]);
2323                                         Vec2Copyf(mvert_fake[2].co, osface->uv[2]);
2324                                         Vec2Copyf(mvert_fake[3].co, osface->uv[3]);
2325                                         //printf("before %f %f %i %i\n", add_pars[n].fuv[0], add_pars[n].fuv[1], test1, test2);
2326                                         psys_interpolate_face(&mvert_fake, &mface_fake, NULL, &add_pars[n].fuv, &fuv_mod, NULL, NULL, NULL);
2327                                         
2328                                         /* Apply as the UV */
2329                                         Vec2Copyf(add_pars[n].fuv, fuv_mod);
2330                                         //printf("after %f %f\n", add_pars[n].fuv[0], add_pars[n].fuv[1]);
2331                                 }
2332                                 /* Make a fake face, for calculating the derived face's fuv on the original face */
2333                                 //PointInFace2DUV(mface->v4, osface->uv[0], osface->uv[1], osface->uv[2], osface->uv[3], add_pars[n].fuv, fuv_mod);
2334                                 //Vec2Copyf(add_pars[n].fuv, fuv_mod);
2335                                 
2336                                 n++;
2337                         }
2338                 }
2339 #endif
2340 #endif
2341         }
2342         if(n){
2343                 int newtotpart=totpart+n;
2344                 float hairmat[4][4], cur_co[3];
2345                 KDTree *tree=0;
2346                 ParticleData *pa, *new_pars = MEM_callocN(newtotpart*sizeof(ParticleData),"ParticleData new");
2347                 ParticleEditKey *ekey, **key, **new_keys = MEM_callocN(newtotpart*sizeof(ParticleEditKey *),"ParticleEditKey array new");
2348                 HairKey *hkey;
2349
2350                 /* save existing elements */
2351                 memcpy(new_pars, psys->particles, totpart * sizeof(ParticleData));
2352                 memcpy(new_keys, edit->keys, totpart * sizeof(ParticleEditKey*));
2353
2354                 /* change old arrays to new ones */
2355                 if(psys->particles) MEM_freeN(psys->particles);
2356                 psys->particles = new_pars;
2357
2358                 if(edit->keys) MEM_freeN(edit->keys);
2359                 edit->keys = new_keys;
2360
2361                 if(edit->mirror_cache) {
2362                         MEM_freeN(edit->mirror_cache);
2363                         edit->mirror_cache = NULL;
2364                 }
2365
2366                 /* create tree for interpolation */
2367                 if(pset->flag & PE_INTERPOLATE_ADDED && psys->totpart){
2368                         tree=BLI_kdtree_new(psys->totpart);
2369                         
2370                         for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
2371                                 psys_particle_on_dm(ob,psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,cur_co,0,0,0,0,0);
2372                                 BLI_kdtree_insert(tree, i, cur_co, NULL);
2373                         }
2374
2375                         BLI_kdtree_balance(tree);
2376                 }
2377
2378                 psys->totpart = newtotpart;
2379
2380                 /* create new elements */
2381                 pa = psys->particles + totpart;
2382                 key = edit->keys + totpart;
2383
2384                 for(i=totpart; i<newtotpart; i++, pa++, key++){
2385                         memcpy(pa, add_pars + i - totpart, sizeof(ParticleData));
2386                         pa->hair = MEM_callocN(pset->totaddkey * sizeof(HairKey), "BakeKey key add");
2387                         ekey = *key = MEM_callocN(pset->totaddkey * sizeof(ParticleEditKey), "ParticleEditKey add");
2388                         pa->totkey = pset->totaddkey;
2389
2390                         for(k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, ekey++) {
2391                                 ekey->co = hkey->co;
2392                                 ekey->time = &hkey->time;
2393                         }
2394                         
2395                         initialize_particle(pa,i,ob,psys,psmd);
2396                         reset_particle(pa,psys,psmd,ob,0.0,1.0,0,0,0);
2397                         pa->flag |= PARS_EDIT_RECALC;
2398                         if(pset->flag & PE_X_MIRROR)
2399                                 pa->flag |= PARS_TAG; /* signal for duplicate */
2400                         
2401                         framestep = pa->lifetime/(float)(pset->totaddkey-1);
2402
2403                         if(tree){
2404                                 HairKey *hkey;
2405                                 ParticleKey key[3];
2406                                 KDTreeNearest ptn[3];
2407                                 int w, maxw;
2408                                 float maxd, mind, dd, totw=0.0, weight[3];
2409
2410                                 psys_particle_on_dm(ob,psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,0,0);
2411                                 maxw = BLI_kdtree_find_n_nearest(tree,3,co1,NULL,ptn);
2412
2413                                 maxd = ptn[maxw-1].dist;
2414                                 mind = ptn[0].dist;
2415                                 dd = maxd - mind;
2416                                 
2417                                 for(w=0; w<maxw; w++){
2418                                         weight[w] = (float)pow(2.0, (double)(-6.0f * ptn[w].dist / maxd));
2419                                         totw += weight[w];
2420                                 }
2421                                 for(;w<3; w++){
2422                                         weight[w] = 0.0f;
2423                                 }
2424
2425                                 for(w=0; w<maxw; w++)
2426                                         weight[w] /= totw;
2427
2428                                 for(k=0; k<pset->totaddkey; k++) {
2429                                         hkey = pa->hair + k;
2430                                         hkey->time = pa->time + k * framestep;
2431
2432                                         key[0].time = hkey->time/ 100.0f;
2433                                         psys_get_particle_on_path(ob, psys, ptn[0].index, key, 0);
2434                                         VecMulf(key[0].co, weight[0]);
2435                                         
2436                                         if(maxw>1) {
2437                                                 key[1].time = key[0].time;
2438                                                 psys_get_particle_on_path(ob, psys, ptn[1].index, key + 1, 0);
2439                                                 VecMulf(key[1].co, weight[1]);
2440                                                 VECADD(key[0].co, key[0].co, key[1].co);
2441
2442                                                 if(maxw>2) {                                            
2443                                                         key[2].time = key[0].time;
2444                                                         psys_get_particle_on_path(ob, psys, ptn[2].index, key + 2, 0);
2445                                                         VecMulf(key[2].co, weight[2]);
2446                                                         VECADD(key[0].co, key[0].co, key[2].co);
2447                                                 }
2448                                         }
2449
2450                                         if(k==0)
2451                                                 VECSUB(co1, pa->state.co, key[0].co);
2452
2453                                         VECADD(pa->hair[k].co, key[0].co, co1);
2454
2455                                         pa->hair[k].time = key[0].time;
2456                                 }
2457                         }
2458                         else{
2459                                 for(k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
2460                                         VECADDFAC(hkey->co, pa->state.co, pa->state.vel, k * framestep * timestep);
2461                                         pa->hair[k].time += k * framestep;
2462                                 }
2463                         }
2464                         for(k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
2465                                 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
2466                                 Mat4Invert(imat,hairmat);
2467                                 Mat4MulVecfl(imat, hkey->co);
2468                         }
2469                 }
2470                 edit->totkeys = psys_count_keys(psys);
2471
2472                 if(tree)
2473                         BLI_kdtree_free(tree);
2474         }
2475         if(add_pars)
2476                 MEM_freeN(add_pars);
2477         
2478 /* painting onto the deformed mesh, could be an option? */
2479 #if EXPERIMENTAL_DEFORM_ONLY_PAINTING
2480         if (!psmd->dm->deformedOnly)
2481                 dm->release(dm);
2482 #endif
2483 }
2484 static void brush_weight(ParticleSystem *psys, float mat[][4], float imat[][4], int pa_index, int key_index, void *userData)
2485 {
2486         struct { Object *ob; short *mval; float rad; rcti* rect; float dist; float weightfac;} *data = userData;
2487         ParticleData *pa;
2488
2489         /* roots have full weight allways */
2490         if(key_index) {
2491                 pa= &psys->particles[pa_index];
2492                 pa->hair[key_index].weight = data->weightfac;
2493                 pa->flag |= PARS_EDIT_RECALC;
2494         }
2495 }
2496
2497 /* returns 0 if no brush was used */
2498 int PE_brush_particles(void)
2499 {
2500         Object *ob = OBACT;
2501         ParticleSystem *psys = PE_get_current(ob);
2502         ParticleEdit *edit;
2503         ParticleEditSettings *pset = PE_settings();
2504         ParticleSystemModifierData *psmd;
2505         ParticleBrushData *brush;
2506         float vec1[3], vec2[3];
2507         short mval[2], mvalo[2], firsttime = 1, dx, dy;
2508         int selected = 0, flip, removed = 0;
2509
2510         if(!PE_can_edit(psys)) return 0;
2511
2512         edit = psys->edit;
2513         psmd= psys_get_modifier(ob, psys);
2514
2515         flip= (get_qual() == LR_SHIFTKEY);
2516
2517         if(pset->brushtype<0) return 0;
2518         brush= &pset->brush[pset->brushtype];
2519
2520         initgrabz(ob->obmat[3][0], ob->obmat[3][1], ob->obmat[3][2]);
2521
2522         getmouseco_areawin(mvalo);
2523
2524         mval[0] = mvalo[0]; mval[1] = mvalo[1];
2525
2526         while(get_mbut() & L_MOUSE){
2527                 bglFlush();
2528                 glReadBuffer(GL_BACK);
2529                 glDrawBuffer(GL_BACK);
2530                 persp(PERSP_VIEW);
2531
2532                 dx=mval[0]-mvalo[0];
2533                 dy=mval[1]-mvalo[1];
2534                 if(((pset->brushtype == PE_BRUSH_ADD) ?
2535                         (sqrt(dx * dx + dy * dy) > pset->brush[PE_BRUSH_ADD].step) : (dx != 0 || dy != 0))
2536                         || firsttime){
2537                         firsttime = 0;
2538
2539                         selected = (short)count_selected_keys(psys);
2540
2541                         switch(pset->brushtype){
2542                                 case PE_BRUSH_COMB:
2543                                 {
2544                                         struct { Object *ob; short *mval; float rad; rcti* rect; float dist; float *dvec; float combfac;} data;
2545
2546                                         data.ob = ob;
2547                                         data.mval = mval;
2548                                         data.rad = (float)brush->size;
2549
2550                                         data.combfac = (float)(brush->strength - 50) / 50.0f;
2551                                         if(data.combfac < 0.0f)
2552                                                 data.combfac = 1.0f - 9.0f * data.combfac;
2553                                         else
2554                                                 data.combfac = 1.0f - data.combfac;
2555
2556                                         Mat4Invert(ob->imat, ob->obmat);
2557
2558                                         window_to_3d(vec1, mvalo[0], mvalo[1]);
2559                                         window_to_3d(vec2, mval[0], mval[1]);
2560                                         VECSUB(vec1, vec2, vec1);
2561                                         data.dvec = vec1;
2562
2563                                         foreach_mouse_hit_key(selected, psys,brush_comb, &data);
2564                                         break;
2565                                 }
2566                                 case PE_BRUSH_CUT:
2567                                 {
2568                                         struct { short *mval; float rad; rcti* rect; int selected; float cutfac;} data;
2569
2570                                         data.mval = mval;
2571                                         data.rad = (float)brush->size;
2572
2573                                         data.selected = selected;
2574
2575                                         data.cutfac = (float)(brush->strength / 100.0f);
2576
2577                                         if(selected)
2578                                                 foreach_selected_element(psys, brush_cut, &data);
2579                                         else
2580                                                 PE_foreach_element(psys, brush_cut, &data);
2581
2582                                         removed= remove_tagged_elements(ob, psys);
2583                                         if(pset->flag & PE_KEEP_LENGTHS)
2584                                                 recalc_lengths(psys);
2585                                         break;
2586                                 }
2587                                 case PE_BRUSH_LENGTH:
2588                                 {
2589                                         struct { short *mval; float rad; rcti* rect; float dist; float growfac; } data;
2590                                         
2591                                         data.mval = mval;
2592                                         
2593                                         data.rad = (float)brush->size;
2594                                         data.growfac = (float)brush->strength / 5000.0f;
2595
2596                                         if(brush->invert ^ flip)
2597                                                 data.growfac = 1.0f - data.growfac;
2598                                         else
2599                                                 data.growfac = 1.0f + data.growfac;
2600
2601                                         foreach_mouse_hit_element(selected, psys, brush_length, &data);
2602
2603                                         if(pset->flag & PE_KEEP_LENGTHS)
2604                                                 recalc_lengths(psys);
2605                                         break;
2606                                 }
2607                                 case PE_BRUSH_PUFF:
2608                                 {
2609                                         struct { short *mval; float rad; rcti* rect; float dist;
2610                                                 Object *ob; DerivedMesh *dm; float pufffac; int invert; } data;
2611
2612                                         data.ob = ob;
2613                                         data.dm = psmd->dm;
2614                                         data.mval = mval;
2615                                         data.rad = (float)brush->size;
2616
2617                                         data.pufffac = (float)(brush->strength - 50) / 50.0f;
2618                                         if(data.pufffac < 0.0f)
2619                                                 data.pufffac = 1.0f - 9.0f * data.pufffac;
2620                                         else
2621                                                 data.pufffac = 1.0f - data.pufffac;
2622
2623                                         data.invert= (brush->invert ^ flip);
2624                                         Mat4Invert(ob->imat, ob->obmat);
2625
2626                                         foreach_mouse_hit_element(selected, psys, brush_puff, &data);
2627                                         break;
2628                                 }
2629                                 case PE_BRUSH_ADD:
2630                                         if(psys->part->from==PART_FROM_FACE){
2631                                                 brush_add(ob, psys, mval, brush->strength);
2632                                                 if(pset->flag & PE_KEEP_LENGTHS)
2633                                                         recalc_lengths(psys);
2634                                         }
2635                                         break;
2636                                 case PE_BRUSH_WEIGHT:
2637                                 {
2638                                         struct { Object *ob; short *mval; float rad; rcti* rect; float dist; float weightfac;} data;
2639
2640                                         data.ob = ob;
2641                                         data.mval = mval;
2642                                         data.rad = (float)brush->size;
2643
2644                                         data.weightfac = (float)(brush->strength / 100.0f);
2645
2646                                         foreach_mouse_hit_key(selected, psys, brush_weight, &data);
2647                                         break;
2648                                 }
2649                                 case PE_BRUSH_SMOOTH:
2650                                 {
2651                                         struct { Object *ob; short *mval; float rad; rcti* rect; float dist; float vec[3]; int tot; float smoothfac;} data;
2652
2653                                         data.ob = ob;
2654                                         data.mval = mval;
2655                                         data.rad = (float)brush->size;
2656
2657                                         data.vec[0] = data.vec[1] = data.vec[2] = 0.0f;
2658                                         data.tot = 0;
2659
2660                                         data.smoothfac = (float)(brush->strength / 100.0f);
2661
2662                                         Mat4Invert(ob->imat, ob->obmat);
2663
2664                                         foreach_mouse_hit_key(selected, psys, brush_smooth_get, &data);
2665
2666                                         if(data.tot){
2667                                                 VecMulf(data.vec, 1.0f / (float)data.tot);
2668                                                 foreach_mouse_hit_key(selected, psys, brush_smooth_do, &data);
2669                                         }
2670
2671                                         break;
2672                                 }
2673                         }
2674                         if((pset->flag & PE_KEEP_LENGTHS)==0)
2675                                 recalc_lengths(psys);
2676
2677                         if(pset->brushtype == PE_BRUSH_ADD || removed) {
2678                                 if(pset->brushtype == PE_BRUSH_ADD && (pset->flag & PE_X_MIRROR))
2679                                         PE_mirror_x(1);
2680                                 PE_recalc_world_cos(ob,psys);
2681                                 psys_free_path_cache(psys);
2682                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2683                         }
2684                         else
2685                                 PE_update_object(ob, 1);
2686                         
2687                         mvalo[0] = mval[0];
2688                         mvalo[1] = mval[1];
2689                 }
2690
2691                 force_draw(0);
2692
2693                 PIL_sleep_ms(10);
2694                 
2695                 getmouseco_areawin(mval);
2696         }
2697         allqueue(REDRAWVIEW3D, 1);
2698
2699         BIF_undo_push("Brush edit particles");
2700
2701         return 1;
2702 }
2703 static void set_delete_particle(ParticleSystem *psys, int index, void *userData)
2704 {
2705         psys->particles[index].flag |= PARS_TAG;
2706 }
2707 static void set_delete_particle_key(ParticleSystem *psys, int pa_index, int key_index, void *userData)
2708 {
2709         psys->edit->keys[pa_index][key_index].flag |= PEK_TAG;
2710 }
2711 void PE_delete_particle(void)
2712 {
2713         Object *ob=OBACT;
2714         ParticleSystem *psys = PE_get_current(ob);
2715         short event=0;
2716
2717         if(!PE_can_edit(psys)) return;
2718
2719         event= pupmenu("Erase %t|Particle%x2|Key%x1");
2720
2721         if(event<1) return;
2722
2723         if(event==1){
2724                 foreach_selected_key(psys, set_delete_particle_key, 0);
2725                 remove_tagged_keys(ob, psys);
2726                 recalc_lengths(psys);
2727         }
2728         else if(event==2){
2729                 foreach_selected_element(psys, set_delete_particle, 0);
2730                 remove_tagged_elements(ob, psys);
2731                 recalc_lengths(psys);
2732         }
2733
2734         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2735         allqueue(REDRAWVIEW3D, 1);
2736         BIF_undo_push("Delete particles/keys");
2737 }
2738
2739 void PE_mirror_x(int tagged)
2740 {
2741         Object *ob=OBACT;
2742         Mesh *me= (Mesh*)(ob->data);
2743         ParticleSystemModifierData *psmd;
2744         ParticleSystem *psys = PE_get_current(ob);
2745         ParticleEdit *edit;
2746         ParticleData *pa, *newpa, *new_pars;
2747         ParticleEditKey *ekey, **newkey, **key, **new_keys;
2748         HairKey *hkey;
2749         int *mirrorfaces;
2750         int i, k, rotation, totpart, newtotpart;
2751
2752         if(!PE_can_edit(psys)) return;
2753
2754         edit= psys->edit;
2755         psmd= psys_get_modifier(ob, psys);
2756
2757         mirrorfaces= mesh_get_x_mirror_faces(ob);
2758
2759         if(!edit->mirror_cache)
2760                 PE_update_mirror_cache(ob, psys);
2761
2762         totpart= psys->totpart;
2763         newtotpart= psys->totpart;
2764         LOOP_PARTICLES(i,pa) {
2765                 if(pa->flag&PARS_HIDE) continue;
2766
2767                 if(!tagged) {
2768                         if(particle_is_selected(psys, pa)) {
2769                                 if(edit->mirror_cache[i] != -1) {
2770                                         /* already has a mirror, don't need to duplicate */
2771                                         PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
2772                                         continue;
2773                                 }
2774                                 else
2775                                         pa->flag |= PARS_TAG;
2776                         }
2777                 }
2778
2779                 if((pa->flag & PARS_TAG) && mirrorfaces[pa->num*2] != -1)
2780                         newtotpart++;
2781         }
2782
2783         if(newtotpart != psys->totpart) {
2784                 /* allocate new arrays and copy existing */
2785                 new_pars= MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new");
2786                 new_keys= MEM_callocN(newtotpart*sizeof(ParticleEditKey*), "ParticleEditKey new");
2787
2788                 memcpy(new_pars, psys->particles, totpart*sizeof(ParticleData));
2789                 memcpy(new_keys, edit->keys, totpart*sizeof(ParticleEditKey*));
2790
2791                 if(psys->particles) MEM_freeN(psys->particles);
2792                 psys->particles= new_pars;
2793
2794                 if(edit->keys) MEM_freeN(edit->keys);
2795                 edit->keys= new_keys;
2796
2797                 if(edit->mirror_cache) {
2798                         MEM_freeN(edit->mirror_cache);
2799                         edit->mirror_cache= NULL;
2800                 }
2801
2802                 psys->totpart= newtotpart;
2803                         
2804                 /* create new elements */
2805                 pa= psys->particles;
2806                 newpa= psys->particles + totpart;
2807                 key= edit->keys;
2808                 newkey= edit->keys + totpart;
2809
2810                 for(i=0; i<totpart; i++, pa++, key++) {
2811                         if(pa->flag&PARS_HIDE) continue;
2812
2813                         if(!(pa->flag & PARS_TAG) || mirrorfaces[pa->num*2] == -1)
2814                                 continue;
2815
2816                         /* duplicate */
2817                         *newpa= *pa;
2818                         if(pa->hair) newpa->hair= MEM_dupallocN(pa->hair);
2819                         if(pa->keys) newpa->keys= MEM_dupallocN(pa->keys);
2820                         if(*key) *newkey= MEM_dupallocN(*key);
2821
2822                         /* rotate weights according to vertex index rotation */
2823                         rotation= mirrorfaces[pa->num*2+1];
2824                         newpa->fuv[0]= pa->fuv[2];
2825                         newpa->fuv[1]= pa->fuv[1];
2826                         newpa->fuv[2]= pa->fuv[0];
2827                         newpa->fuv[3]= pa->fuv[3];
2828                         while(rotation-- > 0)
2829                                 if(me->mface[pa->num].v4)
2830                                         SHIFT4(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2], newpa->fuv[3])
2831                                 else
2832                                         SHIFT3(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2])
2833
2834                         /* assign face inddex */
2835                         newpa->num= mirrorfaces[pa->num*2];
2836                         newpa->num_dmcache= psys_particle_dm_face_lookup(ob,psmd->dm,newpa->num,newpa->fuv, NULL);
2837
2838                         /* update edit key pointers */
2839                         ekey= *newkey;
2840                         for(k=0, hkey=newpa->hair; k<newpa->totkey; k++, hkey++, ekey++) {
2841                                 ekey->co= hkey->co;
2842                                 ekey->time= &hkey->time;
2843                         }
2844
2845                         /* map key positions as mirror over x axis */
2846                         PE_mirror_particle(ob, psmd->dm, psys, pa, newpa);
2847
2848                         newpa++;
2849                         newkey++;
2850                 }
2851
2852                 edit->totkeys = psys_count_keys(psys);
2853         }
2854
2855         for(pa=psys->particles, i=0; i<psys->totpart; i++, pa++)
2856                 pa->flag &= ~PARS_TAG;
2857
2858         MEM_freeN(mirrorfaces);
2859
2860         if(!tagged) {
2861                 PE_recalc_world_cos(ob,psys);
2862                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2863                 allqueue(REDRAWVIEW3D, 1);
2864                 BIF_undo_push("Mirror particles");
2865         }
2866 }
2867
2868 void PE_selectbrush_menu(void)
2869 {
2870         ParticleEditSettings *pset= PE_settings();
2871         int val;
2872         
2873         pupmenu_set_active(pset->brushtype);
2874         
2875         val= pupmenu("Select Brush%t|None %x0|Comb %x1|Smooth %x7|Weight %x6|Add %x5|Length %x3|Puff %x4|Cut %x2");
2876
2877         if(val>=0) {
2878                 pset->brushtype= val-1;
2879                 allqueue(REDRAWVIEW3D, 1);
2880         }
2881 }
2882
2883 /************************************************/
2884 /*                      Particle Edit Undo                                      */
2885 /************************************************/
2886 static void free_ParticleUndo(ParticleUndo *undo)
2887 {
2888         ParticleData *pa;
2889         int i;
2890
2891         for(i=0, pa=undo->particles; i<undo->totpart; i++, pa++) {
2892                 if(pa->hair)
2893                         MEM_freeN(pa->hair);
2894                 if(undo->keys[i])
2895                         MEM_freeN(undo->keys[i]);
2896         }
2897         if(undo->keys)
2898                 MEM_freeN(undo->keys);
2899
2900         if(undo->particles)
2901                 MEM_freeN(undo->particles);
2902
2903         //if(undo->emitter_cosnos)
2904         //      MEM_freeN(undo->emitter_cosnos);
2905 }
2906 static void make_ParticleUndo(ParticleSystem *psys, ParticleUndo *undo)
2907 {
2908         ParticleData *pa,*upa;
2909         int i;
2910
2911         undo->totpart = psys->totpart;
2912         undo->totkeys = psys->edit->totkeys;
2913
2914         upa = undo->particles = MEM_dupallocN(psys->particles);
2915         undo->keys = MEM_dupallocN(psys->edit->keys);
2916         
2917         for(i=0, pa=psys->particles; i<undo->totpart; i++, pa++, upa++) {
2918                 upa->hair = MEM_dupallocN(pa->hair);
2919                 undo->keys[i] = MEM_dupallocN(psys->edit->keys[i]);
2920                 /* no need to update edit key->co & key->time pointers here */
2921         }
2922 }
2923 static void get_ParticleUndo(ParticleSystem *psys, ParticleUndo *undo)
2924 {
2925         ParticleData *pa, *upa;
2926         ParticleEditKey *key;
2927         HairKey *hkey;
2928         int i, k, totpart = psys->totpart;
2929
2930         LOOP_PARTICLES(i,pa) {
2931                 if(pa->hair)
2932                         MEM_freeN(pa->hair);
2933
2934                 if(psys->edit->keys[i])
2935                         MEM_freeN(psys->edit->keys[i]);
2936         }
2937         if(psys->particles)
2938                 MEM_freeN(psys->particles);
2939         if(psys->edit->keys)
2940                 MEM_freeN(psys->edit->keys);
2941         if(psys->edit->mirror_cache) {
2942                 MEM_freeN(psys->edit->mirror_cache);
2943                 psys->edit->mirror_cache= NULL;
2944         }
2945
2946         pa = psys->particles = MEM_dupallocN(undo->particles);
2947         psys->edit->keys = MEM_dupallocN(undo->keys);
2948
2949         for(i=0,upa=undo->particles; i<undo->totpart; i++, upa++, pa++){
2950                 hkey = pa->hair = MEM_dupallocN(upa->hair);
2951                 key = psys->edit->keys[i] = MEM_dupallocN(undo->keys[i]);
2952                 for(k=0; k<pa->totkey; k++, hkey++, key++) {
2953                         key->co = hkey->co;
2954                         key->time = &hkey->time;
2955                 }
2956         }
2957
2958         psys->totpart = undo->totpart;
2959         psys->edit->totkeys = undo->totkeys;
2960 }
2961 void PE_undo_push(char *str)
2962 {
2963         ParticleSystem *psys = PE_get_current(OBACT);
2964         ParticleEdit *edit = 0;
2965         ParticleUndo *undo;
2966         int nr;
2967
2968         if(!PE_can_edit(psys)) return;
2969         edit = psys->edit;
2970
2971         /* remove all undos after (also when curundo==NULL) */
2972         while(edit->undo.last != edit->curundo) {
2973                 undo= edit->undo.last;
2974                 BLI_remlink(&edit->undo, undo);
2975                 free_ParticleUndo(undo);
2976                 MEM_freeN(undo);
2977         }
2978
2979         /* make new */
2980         edit->curundo= undo= MEM_callocN(sizeof(ParticleUndo), "particle undo file");
2981         strncpy(undo->name, str, 64-1);
2982         BLI_addtail(&edit->undo, undo);
2983         
2984         /* and limit amount to the maximum */
2985         nr= 0;
2986         undo= edit->undo.last;
2987         while(undo) {
2988                 nr++;
2989                 if(nr==U.undosteps) break;
2990                 undo= undo->prev;
2991         }
2992         if(undo) {
2993                 while(edit->undo.first!=undo) {
2994                         ParticleUndo *first= edit->undo.first;
2995                         BLI_remlink(&edit->undo, first);
2996                         free_ParticleUndo(first);
2997                         MEM_freeN(first);
2998                 }
2999         }
3000
3001         /* copy  */
3002         make_ParticleUndo(psys,edit->curundo);
3003 }
3004 void PE_undo_step(int step)
3005 {       
3006         ParticleSystem *psys = PE_get_current(OBACT);
3007         ParticleEdit *edit = 0;
3008
3009         if(!PE_can_edit(psys)) return;
3010         edit=psys->edit;
3011
3012         if(step==0) {
3013                 get_ParticleUndo(psys,edit->curundo);
3014         }
3015         else if(step==1) {
3016                 
3017                 if(edit->curundo==NULL || edit->curundo->prev==NULL) error("No more steps to undo");
3018                 else {
3019                         if(G.f & G_DEBUG) printf("undo %s\n", edit->curundo->name);
3020                         edit->curundo= edit->curundo->prev;
3021                         get_ParticleUndo(psys, edit->curundo);
3022                 }
3023         }
3024         else {
3025                 /* curundo has to remain current situation! */
3026                 
3027                 if(edit->curundo==NULL || edit->curundo->next==NULL) error("No more steps to redo");
3028                 else {
3029                         get_ParticleUndo(psys, edit->curundo->next);
3030                         edit->curundo= edit->curundo->next;
3031                         if(G.f & G_DEBUG) printf("redo %s\n", edit->curundo->name);
3032                 }
3033         }
3034
3035         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
3036         allqueue(REDRAWVIEW3D, 1);
3037         allqueue(REDRAWBUTSEDIT, 0);
3038         allqueue(REDRAWIMAGE, 0);
3039 }
3040 static void ParticleUndo_number(ParticleEdit *edit, int nr)
3041 {
3042         ParticleUndo *undo;
3043         int a=1;
3044         
3045         for(undo= edit->undo.first; undo; undo= undo->next, a++) {
3046                 if(a==nr) break;
3047         }
3048         edit->curundo= undo;
3049         PE_undo_step(0);
3050 }
3051 static void ParticleUndo_clear(ParticleSystem *psys)
3052 {
3053         ParticleUndo *undo;
3054         ParticleEdit *edit;
3055
3056         if(psys==0) return;
3057
3058         edit = psys->edit;
3059
3060         if(edit==0) return;
3061         
3062         undo= edit->undo.first;
3063         while(undo) {
3064                 free_ParticleUndo(undo);
3065                 undo= undo->next;
3066         }
3067         BLI_freelistN(&edit->undo);
3068         edit->curundo= NULL;
3069 }
3070 void PE_undo(void)
3071 {
3072         PE_undo_step(1);
3073 }
3074 void PE_redo(void)
3075 {
3076         PE_undo_step(-1);
3077 }
3078 void PE_undo_menu(void)
3079 {
3080         ParticleSystem *psys = PE_get_current(OBACT);
3081         ParticleEdit *edit = 0;
3082         ParticleUndo *undo;
3083         DynStr *ds;
3084         short event;
3085         char *menu;
3086
3087         if(!PE_can_edit(psys)) return;
3088         edit = psys->edit;
3089         
3090         ds= BLI_dynstr_new();
3091
3092         BLI_dynstr_append(ds, "Particlemode Undo History %t");
3093         
3094         for(undo= edit->undo.first; undo; undo= undo->next) {
3095                 BLI_dynstr_append(ds, "|");
3096                 BLI_dynstr_append(ds, undo->name);
3097         }
3098         
3099         menu= BLI_dynstr_get_cstring(ds);
3100         BLI_dynstr_free(ds);
3101         
3102         event= pupmenu_col(menu, 20);
3103         MEM_freeN(menu);
3104         
3105         if(event>0) ParticleUndo_number(edit,event);
3106 }
3107
3108 void PE_get_colors(char sel[4], char nosel[4])
3109 {
3110         BIF_GetThemeColor3ubv(TH_EDGE_SELECT, sel);
3111         BIF_GetThemeColor3ubv(TH_WIRE, nosel);
3112 }
3113
3114 int PE_minmax(float *min, float *max)
3115 {
3116         Object *ob = OBACT;
3117         ParticleSystem *psys = PE_get_current(ob);
3118         ParticleSystemModifierData *psmd;
3119         ParticleData *pa;
3120         ParticleEditKey *key;
3121         float co[3], mat[4][4];
3122         int i, k, totpart, ok = 0;
3123
3124         if(!PE_can_edit(psys)) return ok;
3125         
3126         psmd= psys_get_modifier(ob, psys);
3127         totpart= psys->totpart;
3128
3129         LOOP_PARTICLES(i,pa){
3130                 if(pa->flag&PARS_HIDE) continue;
3131
3132                 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
3133
3134                 LOOP_KEYS(k,key){
3135                         if(key->flag&PEK_SELECT) {
3136                                 VECCOPY(co, key->co);
3137                                 Mat4MulVecfl(mat, co);
3138                                 DO_MINMAX(co, min, max);                
3139                                 ok= 1;
3140                         }
3141                 }
3142         }
3143
3144         if(!ok) {
3145                 minmax_object(ob, min, max);
3146                 ok= 1;
3147         }
3148   
3149         return ok;
3150 }
3151