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