svn merge -r36603:36628 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / editors / physics / particle_object.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2009 Blender Foundation.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/physics/particle_object.c
29  *  \ingroup edphys
30  */
31
32
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "DNA_meshdata_types.h"
39 #include "DNA_modifier_types.h"
40 #include "DNA_scene_types.h"
41
42 #include "BLI_math.h"
43 #include "BLI_listbase.h"
44 #include "BLI_utildefines.h"
45
46 #include "BKE_context.h"
47 #include "BKE_depsgraph.h"
48 #include "BKE_DerivedMesh.h"
49 #include "BKE_cdderivedmesh.h"
50 #include "BKE_global.h"
51 #include "BKE_main.h"
52 #include "BKE_particle.h"
53 #include "BKE_pointcache.h"
54
55
56 #include "RNA_access.h"
57 #include "RNA_define.h"
58
59 #include "WM_api.h"
60 #include "WM_types.h"
61
62 #include "ED_particle.h"
63 #include "ED_screen.h"
64
65 #include "physics_intern.h"
66
67 /********************** particle system slot operators *********************/
68
69 static int particle_system_add_exec(bContext *C, wmOperator *UNUSED(op))
70 {
71         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
72         Scene *scene = CTX_data_scene(C);
73
74         if(!scene || !ob)
75                 return OPERATOR_CANCELLED;
76
77         object_add_particle_system(scene, ob, NULL);
78         
79         WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
80         WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
81         
82         return OPERATOR_FINISHED;
83 }
84
85 void OBJECT_OT_particle_system_add(wmOperatorType *ot)
86 {
87         /* identifiers */
88         ot->name= "Add Particle System Slot";
89         ot->idname= "OBJECT_OT_particle_system_add";
90         ot->description="Add a particle system";
91         
92         /* api callbacks */
93         ot->poll= ED_operator_object_active_editable;
94         ot->exec= particle_system_add_exec;
95         
96         /* flags */
97         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
98 }
99
100 static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op))
101 {
102         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
103         Scene *scene = CTX_data_scene(C);
104         int mode_orig = ob->mode;
105         if(!scene || !ob)
106                 return OPERATOR_CANCELLED;
107
108         object_remove_particle_system(scene, ob);
109
110         /* possible this isn't the active object
111          * object_remove_particle_system() clears the mode on the last psys
112          * */
113         if(mode_orig & OB_MODE_PARTICLE_EDIT)
114                 if((ob->mode & OB_MODE_PARTICLE_EDIT)==0)
115                         if(scene->basact && scene->basact->object==ob)
116                                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
117
118         WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
119         WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
120         
121         return OPERATOR_FINISHED;
122 }
123
124 void OBJECT_OT_particle_system_remove(wmOperatorType *ot)
125 {
126         /* identifiers */
127         ot->name= "Remove Particle System Slot";
128         ot->idname= "OBJECT_OT_particle_system_remove";
129         ot->description="Remove the selected particle system";
130         
131         /* api callbacks */
132         ot->poll= ED_operator_object_active_editable;
133         ot->exec= particle_system_remove_exec;
134
135         /* flags */
136         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
137 }
138
139 /********************** new particle settings operator *********************/
140
141 static int psys_poll(bContext *C)
142 {
143         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
144         return (ptr.data != NULL);
145 }
146
147 static int new_particle_settings_exec(bContext *C, wmOperator *UNUSED(op))
148 {
149         Scene *scene = CTX_data_scene(C);
150         Main *bmain= CTX_data_main(C);
151         ParticleSystem *psys;
152         ParticleSettings *part = NULL;
153         Object *ob;
154         PointerRNA ptr;
155
156         ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
157
158         psys = ptr.data;
159
160         /* add or copy particle setting */
161         if(psys->part)
162                 part= psys_copy_settings(psys->part);
163         else
164                 part= psys_new_settings("ParticleSettings", bmain);
165
166         ob= ptr.id.data;
167
168         if(psys->part)
169                 psys->part->id.us--;
170
171         psys->part = part;
172
173         psys_check_boid_data(psys);
174
175         DAG_scene_sort(bmain, scene);
176         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
177
178         WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
179         
180         return OPERATOR_FINISHED;
181 }
182
183 void PARTICLE_OT_new(wmOperatorType *ot)
184 {
185         /* identifiers */
186         ot->name= "New Particle Settings";
187         ot->idname= "PARTICLE_OT_new";
188         ot->description="Add new particle settings";
189         
190         /* api callbacks */
191         ot->exec= new_particle_settings_exec;
192         ot->poll= psys_poll;
193
194         /* flags */
195         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
196 }
197
198 /********************** keyed particle target operators *********************/
199
200 static int new_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
201 {
202         Main *bmain = CTX_data_main(C);
203         Scene *scene = CTX_data_scene(C);
204         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
205         ParticleSystem *psys= ptr.data;
206         Object *ob = ptr.id.data;
207
208         ParticleTarget *pt;
209
210         if(!psys)
211                 return OPERATOR_CANCELLED;
212
213         pt = psys->targets.first;
214         for(; pt; pt=pt->next)
215                 pt->flag &= ~PTARGET_CURRENT;
216
217         pt = MEM_callocN(sizeof(ParticleTarget), "keyed particle target");
218
219         pt->flag |= PTARGET_CURRENT;
220         pt->psys = 1;
221
222         BLI_addtail(&psys->targets, pt);
223
224         DAG_scene_sort(bmain, scene);
225         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
226
227         WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
228         
229         return OPERATOR_FINISHED;
230 }
231
232 void PARTICLE_OT_new_target(wmOperatorType *ot)
233 {
234         /* identifiers */
235         ot->name= "New Particle Target";
236         ot->idname= "PARTICLE_OT_new_target";
237         ot->description="Add a new particle target";
238         
239         /* api callbacks */
240         ot->exec= new_particle_target_exec;
241
242         /* flags */
243         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
244 }
245
246 static int remove_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
247 {
248         Main *bmain = CTX_data_main(C);
249         Scene *scene = CTX_data_scene(C);
250         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
251         ParticleSystem *psys= ptr.data;
252         Object *ob = ptr.id.data;
253
254         ParticleTarget *pt;
255
256         if(!psys)
257                 return OPERATOR_CANCELLED;
258
259         pt = psys->targets.first;
260         for(; pt; pt=pt->next) {
261                 if(pt->flag & PTARGET_CURRENT) {
262                         BLI_remlink(&psys->targets, pt);
263                         MEM_freeN(pt);
264                         break;
265                 }
266
267         }
268         pt = psys->targets.last;
269
270         if(pt)
271                 pt->flag |= PTARGET_CURRENT;
272
273         DAG_scene_sort(bmain, scene);
274         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
275
276         WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
277         
278         return OPERATOR_FINISHED;
279 }
280
281 void PARTICLE_OT_target_remove(wmOperatorType *ot)
282 {
283         /* identifiers */
284         ot->name= "Remove Particle Target";
285         ot->idname= "PARTICLE_OT_target_remove";
286         ot->description="Remove the selected particle target";
287         
288         /* api callbacks */
289         ot->exec= remove_particle_target_exec;
290
291         /* flags */
292         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
293 }
294
295 /************************ move up particle target operator *********************/
296
297 static int target_move_up_exec(bContext *C, wmOperator *UNUSED(op))
298 {
299         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
300         ParticleSystem *psys= ptr.data;
301         Object *ob = ptr.id.data;
302         ParticleTarget *pt;
303
304         if(!psys)
305                 return OPERATOR_CANCELLED;
306         
307         pt = psys->targets.first;
308         for(; pt; pt=pt->next) {
309                 if(pt->flag & PTARGET_CURRENT && pt->prev) {
310                         BLI_remlink(&psys->targets, pt);
311                         BLI_insertlink(&psys->targets, pt->prev->prev, pt);
312
313                         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
314                         WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
315                         break;
316                 }
317         }
318         
319         return OPERATOR_FINISHED;
320 }
321
322 void PARTICLE_OT_target_move_up(wmOperatorType *ot)
323 {
324         ot->name= "Move Up Target";
325         ot->idname= "PARTICLE_OT_target_move_up";
326         ot->description= "Move particle target up in the list";
327         
328         ot->exec= target_move_up_exec;
329         
330         /* flags */
331         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
332 }
333
334 /************************ move down particle target operator *********************/
335
336 static int target_move_down_exec(bContext *C, wmOperator *UNUSED(op))
337 {
338         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
339         ParticleSystem *psys= ptr.data;
340         Object *ob = ptr.id.data;
341         ParticleTarget *pt;
342
343         if(!psys)
344                 return OPERATOR_CANCELLED;
345         pt = psys->targets.first;
346         for(; pt; pt=pt->next) {
347                 if(pt->flag & PTARGET_CURRENT && pt->next) {
348                         BLI_remlink(&psys->targets, pt);
349                         BLI_insertlink(&psys->targets, pt->next, pt);
350
351                         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
352                         WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
353                         break;
354                 }
355         }
356         
357         return OPERATOR_FINISHED;
358 }
359
360 void PARTICLE_OT_target_move_down(wmOperatorType *ot)
361 {
362         ot->name= "Move Down Target";
363         ot->idname= "PARTICLE_OT_target_move_down";
364         ot->description= "Move particle target down in the list";
365         
366         ot->exec= target_move_down_exec;
367         
368         /* flags */
369         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
370 }
371
372 /************************ move up particle dupliweight operator *********************/
373
374 static int dupliob_move_up_exec(bContext *C, wmOperator *UNUSED(op))
375 {
376         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
377         ParticleSystem *psys= ptr.data;
378         ParticleSettings *part;
379         ParticleDupliWeight *dw;
380
381         if(!psys)
382                 return OPERATOR_CANCELLED;
383
384         part = psys->part;
385         for(dw=part->dupliweights.first; dw; dw=dw->next) {
386                 if(dw->flag & PART_DUPLIW_CURRENT && dw->prev) {
387                         BLI_remlink(&part->dupliweights, dw);
388                         BLI_insertlink(&part->dupliweights, dw->prev->prev, dw);
389
390                         WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
391                         break;
392                 }
393         }
394         
395         return OPERATOR_FINISHED;
396 }
397
398 void PARTICLE_OT_dupliob_move_up(wmOperatorType *ot)
399 {
400         ot->name= "Move Up Dupli Object";
401         ot->idname= "PARTICLE_OT_dupliob_move_up";
402         ot->description= "Move dupli object up in the list";
403         
404         ot->exec= dupliob_move_up_exec;
405         
406         /* flags */
407         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
408 }
409
410 /********************** particle dupliweight operators *********************/
411
412 static int copy_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op))
413 {
414         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
415         ParticleSystem *psys= ptr.data;
416         ParticleSettings *part;
417         ParticleDupliWeight *dw;
418
419         if(!psys)
420                 return OPERATOR_CANCELLED;
421         part = psys->part;
422         for(dw=part->dupliweights.first; dw; dw=dw->next) {
423                 if(dw->flag & PART_DUPLIW_CURRENT) {
424                         dw->flag &= ~PART_DUPLIW_CURRENT;
425                         dw = MEM_dupallocN(dw);
426                         dw->flag |= PART_DUPLIW_CURRENT;
427                         BLI_addhead(&part->dupliweights, dw);
428
429                         WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
430                         break;
431                 }
432         }
433         
434         return OPERATOR_FINISHED;
435 }
436
437 void PARTICLE_OT_dupliob_copy(wmOperatorType *ot)
438 {
439         /* identifiers */
440         ot->name= "Copy Particle Dupliob";
441         ot->idname= "PARTICLE_OT_dupliob_copy";
442         ot->description="Duplicate the current dupliobject";
443         
444         /* api callbacks */
445         ot->exec= copy_particle_dupliob_exec;
446
447         /* flags */
448         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
449 }
450
451 static int remove_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op))
452 {
453         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
454         ParticleSystem *psys= ptr.data;
455         ParticleSettings *part;
456         ParticleDupliWeight *dw;
457
458         if(!psys)
459                 return OPERATOR_CANCELLED;
460
461         part = psys->part;
462         for(dw=part->dupliweights.first; dw; dw=dw->next) {
463                 if(dw->flag & PART_DUPLIW_CURRENT) {
464                         BLI_remlink(&part->dupliweights, dw);
465                         MEM_freeN(dw);
466                         break;
467                 }
468
469         }
470         dw = part->dupliweights.last;
471
472         if(dw)
473                 dw->flag |= PART_DUPLIW_CURRENT;
474
475         WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
476         
477         return OPERATOR_FINISHED;
478 }
479
480 void PARTICLE_OT_dupliob_remove(wmOperatorType *ot)
481 {
482         /* identifiers */
483         ot->name= "Remove Particle Dupliobject";
484         ot->idname= "PARTICLE_OT_dupliob_remove";
485         ot->description="Remove the selected dupliobject";
486         
487         /* api callbacks */
488         ot->exec= remove_particle_dupliob_exec;
489
490         /* flags */
491         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
492 }
493
494 /************************ move down particle dupliweight operator *********************/
495
496 static int dupliob_move_down_exec(bContext *C, wmOperator *UNUSED(op))
497 {
498         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
499         ParticleSystem *psys= ptr.data;
500         ParticleSettings *part;
501         ParticleDupliWeight *dw;
502
503         if(!psys)
504                 return OPERATOR_CANCELLED;
505
506         part = psys->part;
507         for(dw=part->dupliweights.first; dw; dw=dw->next) {
508                 if(dw->flag & PART_DUPLIW_CURRENT && dw->next) {
509                         BLI_remlink(&part->dupliweights, dw);
510                         BLI_insertlink(&part->dupliweights, dw->next, dw);
511
512                         WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
513                         break;
514                 }
515         }
516         
517         return OPERATOR_FINISHED;
518 }
519
520 void PARTICLE_OT_dupliob_move_down(wmOperatorType *ot)
521 {
522         ot->name= "Move Down Dupli Object";
523         ot->idname= "PARTICLE_OT_dupliob_move_down";
524         ot->description= "Move dupli object down in the list";
525         
526         ot->exec= dupliob_move_down_exec;
527         
528         /* flags */
529         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
530 }
531
532 /************************ connect/disconnect hair operators *********************/
533
534 static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
535 {
536         ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys);
537         ParticleEditSettings *pset= PE_settings(scene);
538         ParticleData *pa;
539         PTCacheEdit *edit;
540         PTCacheEditPoint *point;
541         PTCacheEditKey *ekey = NULL;
542         HairKey *key;
543         int i, k;
544         float hairmat[4][4];
545
546         if(!ob || !psys || psys->flag & PSYS_GLOBAL_HAIR)
547                 return;
548
549         if(!psys->part || psys->part->type != PART_HAIR)
550                 return;
551         
552         edit = psys->edit;
553         point= edit ? edit->points : NULL;
554
555         for(i=0, pa=psys->particles; i<psys->totpart; i++,pa++) {
556                 if(point) {
557                         ekey = point->keys;
558                         point++;
559                 }
560
561                 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
562
563                 for(k=0,key=pa->hair; k<pa->totkey; k++,key++) {
564                         mul_m4_v3(hairmat,key->co);
565                         
566                         if(ekey) {
567                                 ekey->flag &= ~PEK_USE_WCO;
568                                 ekey++;
569                         }
570                 }
571         }
572
573         psys_free_path_cache(psys, psys->edit);
574
575         psys->flag |= PSYS_GLOBAL_HAIR;
576
577         if(ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_PUFF))
578                 pset->brushtype = PE_BRUSH_NONE;
579
580         PE_update_object(scene, ob, 0);
581 }
582
583 static int disconnect_hair_exec(bContext *C, wmOperator *op)
584 {
585         Scene *scene= CTX_data_scene(C);
586         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
587         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
588         ParticleSystem *psys= NULL;
589         int all = RNA_boolean_get(op->ptr, "all");
590
591         if(!ob)
592                 return OPERATOR_CANCELLED;
593
594         if(all) {
595                 for(psys=ob->particlesystem.first; psys; psys=psys->next) {
596                         disconnect_hair(scene, ob, psys);
597                 }
598         }
599         else {
600                 psys = ptr.data;
601                 disconnect_hair(scene, ob, psys);
602         }
603
604         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
605         WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
606
607         return OPERATOR_FINISHED;
608 }
609
610 void PARTICLE_OT_disconnect_hair(wmOperatorType *ot)
611 {
612         ot->name= "Disconnect Hair";
613         ot->description= "Disconnect hair from the emitter mesh";
614         ot->idname= "PARTICLE_OT_disconnect_hair";
615         
616         ot->exec= disconnect_hair_exec;
617         
618         /* flags */
619         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
620
621         RNA_def_boolean(ot->srna, "all", 0, "All hair", "Disconnect all hair systems from the emitter mesh");
622 }
623
624 static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
625 {
626         ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys);
627         ParticleData *pa;
628         PTCacheEdit *edit;
629         PTCacheEditPoint *point;
630         PTCacheEditKey *ekey = NULL;
631         HairKey *key;
632         BVHTreeFromMesh bvhtree= {NULL};
633         BVHTreeNearest nearest;
634         MFace *mface;
635         DerivedMesh *dm = NULL;
636         int numverts;
637         int i, k;
638         float hairmat[4][4], imat[4][4];
639         float v[4][3], vec[3];
640
641         if(!psys || !psys->part || psys->part->type != PART_HAIR)
642                 return;
643         
644         edit= psys->edit;
645         point=  edit ? edit->points : NULL;
646         
647         if(psmd->dm->deformedOnly)
648                 /* we don't want to mess up psmd->dm when converting to global coordinates below */
649                 dm= CDDM_copy(psmd->dm, 0);
650         else
651                 dm= mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
652
653         numverts = dm->getNumVerts (dm);
654
655         /* convert to global coordinates */
656         for (i=0; i<numverts; i++)
657                 mul_m4_v3(ob->obmat, CDDM_get_vert(dm, i)->co);
658
659         bvhtree_from_mesh_faces(&bvhtree, dm, 0.0, 2, 6);
660
661         for(i=0, pa= psys->particles; i<psys->totpart; i++,pa++) {
662                 key = pa->hair;
663
664                 nearest.index = -1;
665                 nearest.dist = FLT_MAX;
666
667                 BLI_bvhtree_find_nearest(bvhtree.tree, key->co, &nearest, bvhtree.nearest_callback, &bvhtree);
668
669                 if(nearest.index == -1) {
670                         if (G.f & G_DEBUG)
671                                 printf("No nearest point found for hair root!");
672                         continue;
673                 }
674
675                 mface = CDDM_get_tessface(dm,nearest.index);
676
677                 copy_v3_v3(v[0], CDDM_get_vert(dm,mface->v1)->co);
678                 copy_v3_v3(v[1], CDDM_get_vert(dm,mface->v2)->co);
679                 copy_v3_v3(v[2], CDDM_get_vert(dm,mface->v3)->co);
680                 if(mface->v4) {
681                         copy_v3_v3(v[3], CDDM_get_vert(dm,mface->v4)->co);
682                         interp_weights_poly_v3( pa->fuv,v, 4, nearest.co);
683                 }
684                 else
685                         interp_weights_poly_v3( pa->fuv,v, 3, nearest.co);
686
687                 pa->num = nearest.index;
688                 pa->num_dmcache = psys_particle_dm_face_lookup(ob,psmd->dm,pa->num,pa->fuv,NULL);
689                 
690                 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
691                 invert_m4_m4(imat,hairmat);
692
693                 VECSUB(vec, nearest.co, key->co);
694
695                 if(point) {
696                         ekey = point->keys;
697                         point++;
698                 }
699
700                 for(k=0,key=pa->hair; k<pa->totkey; k++,key++) {
701                         VECADD(key->co, key->co, vec);
702                         mul_m4_v3(imat,key->co);
703
704                         if(ekey) {
705                                 ekey->flag |= PEK_USE_WCO;
706                                 ekey++;
707                         }
708                 }
709         }
710
711         free_bvhtree_from_mesh(&bvhtree);
712         dm->release(dm);
713
714         psys_free_path_cache(psys, psys->edit);
715
716         psys->flag &= ~PSYS_GLOBAL_HAIR;
717
718         PE_update_object(scene, ob, 0);
719 }
720
721 static int connect_hair_exec(bContext *C, wmOperator *op)
722 {
723         Scene *scene= CTX_data_scene(C);
724         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
725         PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
726         ParticleSystem *psys= NULL;
727         int all = RNA_boolean_get(op->ptr, "all");
728
729         if(!ob)
730                 return OPERATOR_CANCELLED;
731
732         if(all) {
733                 for(psys=ob->particlesystem.first; psys; psys=psys->next) {
734                         connect_hair(scene, ob, psys);
735                 }
736         }
737         else {
738                 psys = ptr.data;
739                 connect_hair(scene, ob, psys);
740         }
741
742         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
743         WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
744
745         return OPERATOR_FINISHED;
746 }
747
748 void PARTICLE_OT_connect_hair(wmOperatorType *ot)
749 {
750         ot->name= "Connect Hair";
751         ot->description= "Connect hair to the emitter mesh";
752         ot->idname= "PARTICLE_OT_connect_hair";
753         
754         ot->exec= connect_hair_exec;
755         
756         /* flags */
757         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
758
759         RNA_def_boolean(ot->srna, "all", 0, "All hair", "Connect all hair systems to the emitter mesh");
760 }
761