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