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