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