Blender V2.61 - r43446

particle_object.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2009 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): Blender Foundation
00022  *
00023  * ***** END GPL LICENSE BLOCK *****
00024  */
00025 
00031 #include <stdlib.h>
00032 #include <string.h>
00033 
00034 #include "MEM_guardedalloc.h"
00035 
00036 #include "DNA_meshdata_types.h"
00037 #include "DNA_modifier_types.h"
00038 #include "DNA_scene_types.h"
00039 
00040 #include "BLI_math.h"
00041 #include "BLI_listbase.h"
00042 #include "BLI_utildefines.h"
00043 
00044 #include "BKE_context.h"
00045 #include "BKE_depsgraph.h"
00046 #include "BKE_DerivedMesh.h"
00047 #include "BKE_cdderivedmesh.h"
00048 #include "BKE_global.h"
00049 #include "BKE_main.h"
00050 #include "BKE_particle.h"
00051 #include "BKE_pointcache.h"
00052 
00053 
00054 #include "RNA_access.h"
00055 #include "RNA_define.h"
00056 
00057 #include "WM_api.h"
00058 #include "WM_types.h"
00059 
00060 #include "ED_particle.h"
00061 #include "ED_screen.h"
00062 #include "ED_object.h"
00063 
00064 #include "physics_intern.h"
00065 
00066 /********************** particle system slot operators *********************/
00067 
00068 static int particle_system_add_exec(bContext *C, wmOperator *UNUSED(op))
00069 {
00070     Object *ob= ED_object_context(C);
00071     Scene *scene = CTX_data_scene(C);
00072 
00073     if(!scene || !ob)
00074         return OPERATOR_CANCELLED;
00075 
00076     object_add_particle_system(scene, ob, NULL);
00077     
00078     WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
00079     WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
00080     
00081     return OPERATOR_FINISHED;
00082 }
00083 
00084 void OBJECT_OT_particle_system_add(wmOperatorType *ot)
00085 {
00086     /* identifiers */
00087     ot->name= "Add Particle System Slot";
00088     ot->idname= "OBJECT_OT_particle_system_add";
00089     ot->description="Add a particle system";
00090     
00091     /* api callbacks */
00092     ot->poll= ED_operator_object_active_editable;
00093     ot->exec= particle_system_add_exec;
00094     
00095     /* flags */
00096     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00097 }
00098 
00099 static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op))
00100 {
00101     Object *ob= ED_object_context(C);
00102     Scene *scene = CTX_data_scene(C);
00103     int mode_orig = ob->mode;
00104     if(!scene || !ob)
00105         return OPERATOR_CANCELLED;
00106 
00107     object_remove_particle_system(scene, ob);
00108 
00109     /* possible this isn't the active object
00110      * object_remove_particle_system() clears the mode on the last psys
00111      * */
00112     if(mode_orig & OB_MODE_PARTICLE_EDIT)
00113         if((ob->mode & OB_MODE_PARTICLE_EDIT)==0)
00114             if(scene->basact && scene->basact->object==ob)
00115                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
00116 
00117     WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
00118     WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
00119     
00120     return OPERATOR_FINISHED;
00121 }
00122 
00123 void OBJECT_OT_particle_system_remove(wmOperatorType *ot)
00124 {
00125     /* identifiers */
00126     ot->name= "Remove Particle System Slot";
00127     ot->idname= "OBJECT_OT_particle_system_remove";
00128     ot->description="Remove the selected particle system";
00129     
00130     /* api callbacks */
00131     ot->poll= ED_operator_object_active_editable;
00132     ot->exec= particle_system_remove_exec;
00133 
00134     /* flags */
00135     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00136 }
00137 
00138 /********************** new particle settings operator *********************/
00139 
00140 static int psys_poll(bContext *C)
00141 {
00142     PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
00143     return (ptr.data != NULL);
00144 }
00145 
00146 static int new_particle_settings_exec(bContext *C, wmOperator *UNUSED(op))
00147 {
00148     Scene *scene = CTX_data_scene(C);
00149     Main *bmain= CTX_data_main(C);
00150     ParticleSystem *psys;
00151     ParticleSettings *part = NULL;
00152     Object *ob;
00153     PointerRNA ptr;
00154 
00155     ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
00156 
00157     psys = ptr.data;
00158 
00159     /* add or copy particle setting */
00160     if(psys->part)
00161         part= psys_copy_settings(psys->part);
00162     else
00163         part= psys_new_settings("ParticleSettings", bmain);
00164 
00165     ob= ptr.id.data;
00166 
00167     if(psys->part)
00168         psys->part->id.us--;
00169 
00170     psys->part = part;
00171 
00172     psys_check_boid_data(psys);
00173 
00174     DAG_scene_sort(bmain, scene);
00175     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00176 
00177     WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
00178     
00179     return OPERATOR_FINISHED;
00180 }
00181 
00182 void PARTICLE_OT_new(wmOperatorType *ot)
00183 {
00184     /* identifiers */
00185     ot->name= "New Particle Settings";
00186     ot->idname= "PARTICLE_OT_new";
00187     ot->description="Add new particle settings";
00188     
00189     /* api callbacks */
00190     ot->exec= new_particle_settings_exec;
00191     ot->poll= psys_poll;
00192 
00193     /* flags */
00194     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00195 }
00196 
00197 /********************** keyed particle target operators *********************/
00198 
00199 static int new_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
00200 {
00201     Main *bmain = CTX_data_main(C);
00202     Scene *scene = CTX_data_scene(C);
00203     PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
00204     ParticleSystem *psys= ptr.data;
00205     Object *ob = ptr.id.data;
00206 
00207     ParticleTarget *pt;
00208 
00209     if(!psys)
00210         return OPERATOR_CANCELLED;
00211 
00212     pt = psys->targets.first;
00213     for(; pt; pt=pt->next)
00214         pt->flag &= ~PTARGET_CURRENT;
00215 
00216     pt = MEM_callocN(sizeof(ParticleTarget), "keyed particle target");
00217 
00218     pt->flag |= PTARGET_CURRENT;
00219     pt->psys = 1;
00220 
00221     BLI_addtail(&psys->targets, pt);
00222 
00223     DAG_scene_sort(bmain, scene);
00224     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00225 
00226     WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
00227     
00228     return OPERATOR_FINISHED;
00229 }
00230 
00231 void PARTICLE_OT_new_target(wmOperatorType *ot)
00232 {
00233     /* identifiers */
00234     ot->name= "New Particle Target";
00235     ot->idname= "PARTICLE_OT_new_target";
00236     ot->description="Add a new particle target";
00237     
00238     /* api callbacks */
00239     ot->exec= new_particle_target_exec;
00240 
00241     /* flags */
00242     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00243 }
00244 
00245 static int remove_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
00246 {
00247     Main *bmain = CTX_data_main(C);
00248     Scene *scene = CTX_data_scene(C);
00249     PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
00250     ParticleSystem *psys= ptr.data;
00251     Object *ob = ptr.id.data;
00252 
00253     ParticleTarget *pt;
00254 
00255     if(!psys)
00256         return OPERATOR_CANCELLED;
00257 
00258     pt = psys->targets.first;
00259     for(; pt; pt=pt->next) {
00260         if(pt->flag & PTARGET_CURRENT) {
00261             BLI_remlink(&psys->targets, pt);
00262             MEM_freeN(pt);
00263             break;
00264         }
00265 
00266     }
00267     pt = psys->targets.last;
00268 
00269     if(pt)
00270         pt->flag |= PTARGET_CURRENT;
00271 
00272     DAG_scene_sort(bmain, scene);
00273     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00274 
00275     WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
00276     
00277     return OPERATOR_FINISHED;
00278 }
00279 
00280 void PARTICLE_OT_target_remove(wmOperatorType *ot)
00281 {
00282     /* identifiers */
00283     ot->name= "Remove Particle Target";
00284     ot->idname= "PARTICLE_OT_target_remove";
00285     ot->description="Remove the selected particle target";
00286     
00287     /* api callbacks */
00288     ot->exec= remove_particle_target_exec;
00289 
00290     /* flags */
00291     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00292 }
00293 
00294 /************************ move up particle target operator *********************/
00295 
00296 static int target_move_up_exec(bContext *C, wmOperator *UNUSED(op))
00297 {
00298     PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
00299     ParticleSystem *psys= ptr.data;
00300     Object *ob = ptr.id.data;
00301     ParticleTarget *pt;
00302 
00303     if(!psys)
00304         return OPERATOR_CANCELLED;
00305     
00306     pt = psys->targets.first;
00307     for(; pt; pt=pt->next) {
00308         if(pt->flag & PTARGET_CURRENT && pt->prev) {
00309             BLI_remlink(&psys->targets, pt);
00310             BLI_insertlink(&psys->targets, pt->prev->prev, pt);
00311 
00312             DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00313             WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
00314             break;
00315         }
00316     }
00317     
00318     return OPERATOR_FINISHED;
00319 }
00320 
00321 void PARTICLE_OT_target_move_up(wmOperatorType *ot)
00322 {
00323     ot->name= "Move Up Target";
00324     ot->idname= "PARTICLE_OT_target_move_up";
00325     ot->description= "Move particle target up in the list";
00326     
00327     ot->exec= target_move_up_exec;
00328     
00329     /* flags */
00330     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00331 }
00332 
00333 /************************ move down particle target operator *********************/
00334 
00335 static int target_move_down_exec(bContext *C, wmOperator *UNUSED(op))
00336 {
00337     PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
00338     ParticleSystem *psys= ptr.data;
00339     Object *ob = ptr.id.data;
00340     ParticleTarget *pt;
00341 
00342     if(!psys)
00343         return OPERATOR_CANCELLED;
00344     pt = psys->targets.first;
00345     for(; pt; pt=pt->next) {
00346         if(pt->flag & PTARGET_CURRENT && pt->next) {
00347             BLI_remlink(&psys->targets, pt);
00348             BLI_insertlink(&psys->targets, pt->next, pt);
00349 
00350             DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00351             WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
00352             break;
00353         }
00354     }
00355     
00356     return OPERATOR_FINISHED;
00357 }
00358 
00359 void PARTICLE_OT_target_move_down(wmOperatorType *ot)
00360 {
00361     ot->name= "Move Down Target";
00362     ot->idname= "PARTICLE_OT_target_move_down";
00363     ot->description= "Move particle target down in the list";
00364     
00365     ot->exec= target_move_down_exec;
00366     
00367     /* flags */
00368     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00369 }
00370 
00371 /************************ move up particle dupliweight operator *********************/
00372 
00373 static int dupliob_move_up_exec(bContext *C, wmOperator *UNUSED(op))
00374 {
00375     PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
00376     ParticleSystem *psys= ptr.data;
00377     ParticleSettings *part;
00378     ParticleDupliWeight *dw;
00379 
00380     if(!psys)
00381         return OPERATOR_CANCELLED;
00382 
00383     part = psys->part;
00384     for(dw=part->dupliweights.first; dw; dw=dw->next) {
00385         if(dw->flag & PART_DUPLIW_CURRENT && dw->prev) {
00386             BLI_remlink(&part->dupliweights, dw);
00387             BLI_insertlink(&part->dupliweights, dw->prev->prev, dw);
00388 
00389             WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
00390             break;
00391         }
00392     }
00393     
00394     return OPERATOR_FINISHED;
00395 }
00396 
00397 void PARTICLE_OT_dupliob_move_up(wmOperatorType *ot)
00398 {
00399     ot->name= "Move Up Dupli Object";
00400     ot->idname= "PARTICLE_OT_dupliob_move_up";
00401     ot->description= "Move dupli object up in the list";
00402     
00403     ot->exec= dupliob_move_up_exec;
00404     
00405     /* flags */
00406     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00407 }
00408 
00409 /********************** particle dupliweight operators *********************/
00410 
00411 static int copy_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op))
00412 {
00413     PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
00414     ParticleSystem *psys= ptr.data;
00415     ParticleSettings *part;
00416     ParticleDupliWeight *dw;
00417 
00418     if(!psys)
00419         return OPERATOR_CANCELLED;
00420     part = psys->part;
00421     for(dw=part->dupliweights.first; dw; dw=dw->next) {
00422         if(dw->flag & PART_DUPLIW_CURRENT) {
00423             dw->flag &= ~PART_DUPLIW_CURRENT;
00424             dw = MEM_dupallocN(dw);
00425             dw->flag |= PART_DUPLIW_CURRENT;
00426             BLI_addhead(&part->dupliweights, dw);
00427 
00428             WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
00429             break;
00430         }
00431     }
00432     
00433     return OPERATOR_FINISHED;
00434 }
00435 
00436 void PARTICLE_OT_dupliob_copy(wmOperatorType *ot)
00437 {
00438     /* identifiers */
00439     ot->name= "Copy Particle Dupliob";
00440     ot->idname= "PARTICLE_OT_dupliob_copy";
00441     ot->description="Duplicate the current dupliobject";
00442     
00443     /* api callbacks */
00444     ot->exec= copy_particle_dupliob_exec;
00445 
00446     /* flags */
00447     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00448 }
00449 
00450 static int remove_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op))
00451 {
00452     PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
00453     ParticleSystem *psys= ptr.data;
00454     ParticleSettings *part;
00455     ParticleDupliWeight *dw;
00456 
00457     if(!psys)
00458         return OPERATOR_CANCELLED;
00459 
00460     part = psys->part;
00461     for(dw=part->dupliweights.first; dw; dw=dw->next) {
00462         if(dw->flag & PART_DUPLIW_CURRENT) {
00463             BLI_remlink(&part->dupliweights, dw);
00464             MEM_freeN(dw);
00465             break;
00466         }
00467 
00468     }
00469     dw = part->dupliweights.last;
00470 
00471     if(dw)
00472         dw->flag |= PART_DUPLIW_CURRENT;
00473 
00474     WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
00475     
00476     return OPERATOR_FINISHED;
00477 }
00478 
00479 void PARTICLE_OT_dupliob_remove(wmOperatorType *ot)
00480 {
00481     /* identifiers */
00482     ot->name= "Remove Particle Dupliobject";
00483     ot->idname= "PARTICLE_OT_dupliob_remove";
00484     ot->description="Remove the selected dupliobject";
00485     
00486     /* api callbacks */
00487     ot->exec= remove_particle_dupliob_exec;
00488 
00489     /* flags */
00490     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00491 }
00492 
00493 /************************ move down particle dupliweight operator *********************/
00494 
00495 static int dupliob_move_down_exec(bContext *C, wmOperator *UNUSED(op))
00496 {
00497     PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
00498     ParticleSystem *psys= ptr.data;
00499     ParticleSettings *part;
00500     ParticleDupliWeight *dw;
00501 
00502     if(!psys)
00503         return OPERATOR_CANCELLED;
00504 
00505     part = psys->part;
00506     for(dw=part->dupliweights.first; dw; dw=dw->next) {
00507         if(dw->flag & PART_DUPLIW_CURRENT && dw->next) {
00508             BLI_remlink(&part->dupliweights, dw);
00509             BLI_insertlink(&part->dupliweights, dw->next, dw);
00510 
00511             WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
00512             break;
00513         }
00514     }
00515     
00516     return OPERATOR_FINISHED;
00517 }
00518 
00519 void PARTICLE_OT_dupliob_move_down(wmOperatorType *ot)
00520 {
00521     ot->name= "Move Down Dupli Object";
00522     ot->idname= "PARTICLE_OT_dupliob_move_down";
00523     ot->description= "Move dupli object down in the list";
00524     
00525     ot->exec= dupliob_move_down_exec;
00526     
00527     /* flags */
00528     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00529 }
00530 
00531 /************************ connect/disconnect hair operators *********************/
00532 
00533 static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
00534 {
00535     ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys);
00536     ParticleEditSettings *pset= PE_settings(scene);
00537     ParticleData *pa;
00538     PTCacheEdit *edit;
00539     PTCacheEditPoint *point;
00540     PTCacheEditKey *ekey = NULL;
00541     HairKey *key;
00542     int i, k;
00543     float hairmat[4][4];
00544 
00545     if(!ob || !psys || psys->flag & PSYS_GLOBAL_HAIR)
00546         return;
00547 
00548     if(!psys->part || psys->part->type != PART_HAIR)
00549         return;
00550     
00551     edit = psys->edit;
00552     point= edit ? edit->points : NULL;
00553 
00554     for(i=0, pa=psys->particles; i<psys->totpart; i++,pa++) {
00555         if(point) {
00556             ekey = point->keys;
00557             point++;
00558         }
00559 
00560         psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
00561 
00562         for(k=0,key=pa->hair; k<pa->totkey; k++,key++) {
00563             mul_m4_v3(hairmat,key->co);
00564             
00565             if(ekey) {
00566                 ekey->flag &= ~PEK_USE_WCO;
00567                 ekey++;
00568             }
00569         }
00570     }
00571 
00572     psys_free_path_cache(psys, psys->edit);
00573 
00574     psys->flag |= PSYS_GLOBAL_HAIR;
00575 
00576     if(ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_PUFF))
00577         pset->brushtype = PE_BRUSH_NONE;
00578 
00579     PE_update_object(scene, ob, 0);
00580 }
00581 
00582 static int disconnect_hair_exec(bContext *C, wmOperator *op)
00583 {
00584     Scene *scene= CTX_data_scene(C);
00585     Object *ob= ED_object_context(C);
00586     PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
00587     ParticleSystem *psys= NULL;
00588     int all = RNA_boolean_get(op->ptr, "all");
00589 
00590     if(!ob)
00591         return OPERATOR_CANCELLED;
00592 
00593     if(all) {
00594         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
00595             disconnect_hair(scene, ob, psys);
00596         }
00597     }
00598     else {
00599         psys = ptr.data;
00600         disconnect_hair(scene, ob, psys);
00601     }
00602 
00603     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00604     WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
00605 
00606     return OPERATOR_FINISHED;
00607 }
00608 
00609 void PARTICLE_OT_disconnect_hair(wmOperatorType *ot)
00610 {
00611     ot->name= "Disconnect Hair";
00612     ot->description= "Disconnect hair from the emitter mesh";
00613     ot->idname= "PARTICLE_OT_disconnect_hair";
00614     
00615     ot->exec= disconnect_hair_exec;
00616     
00617     /* flags */
00618     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00619 
00620     RNA_def_boolean(ot->srna, "all", 0, "All hair", "Disconnect all hair systems from the emitter mesh");
00621 }
00622 
00623 static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
00624 {
00625     ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys);
00626     ParticleData *pa;
00627     PTCacheEdit *edit;
00628     PTCacheEditPoint *point;
00629     PTCacheEditKey *ekey = NULL;
00630     HairKey *key;
00631     BVHTreeFromMesh bvhtree= {NULL};
00632     BVHTreeNearest nearest;
00633     MFace *mface;
00634     DerivedMesh *dm = NULL;
00635     int numverts;
00636     int i, k;
00637     float hairmat[4][4], imat[4][4];
00638     float v[4][3], vec[3];
00639 
00640     if(!psys || !psys->part || psys->part->type != PART_HAIR)
00641         return;
00642     
00643     edit= psys->edit;
00644     point=  edit ? edit->points : NULL;
00645     
00646     if(psmd->dm->deformedOnly)
00647         /* we don't want to mess up psmd->dm when converting to global coordinates below */
00648         dm= CDDM_copy(psmd->dm);
00649     else
00650         dm= mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
00651 
00652     numverts = dm->getNumVerts (dm);
00653 
00654     /* convert to global coordinates */
00655     for (i=0; i<numverts; i++)
00656         mul_m4_v3(ob->obmat, CDDM_get_vert(dm, i)->co);
00657 
00658     bvhtree_from_mesh_faces(&bvhtree, dm, 0.0, 2, 6);
00659 
00660     for(i=0, pa= psys->particles; i<psys->totpart; i++,pa++) {
00661         key = pa->hair;
00662 
00663         nearest.index = -1;
00664         nearest.dist = FLT_MAX;
00665 
00666         BLI_bvhtree_find_nearest(bvhtree.tree, key->co, &nearest, bvhtree.nearest_callback, &bvhtree);
00667 
00668         if(nearest.index == -1) {
00669             if (G.f & G_DEBUG)
00670                 printf("No nearest point found for hair root!");
00671             continue;
00672         }
00673 
00674         mface = CDDM_get_face(dm,nearest.index);
00675 
00676         copy_v3_v3(v[0], CDDM_get_vert(dm,mface->v1)->co);
00677         copy_v3_v3(v[1], CDDM_get_vert(dm,mface->v2)->co);
00678         copy_v3_v3(v[2], CDDM_get_vert(dm,mface->v3)->co);
00679         if(mface->v4) {
00680             copy_v3_v3(v[3], CDDM_get_vert(dm,mface->v4)->co);
00681             interp_weights_poly_v3( pa->fuv,v, 4, nearest.co);
00682         }
00683         else
00684             interp_weights_poly_v3( pa->fuv,v, 3, nearest.co);
00685 
00686         pa->num = nearest.index;
00687         pa->num_dmcache = psys_particle_dm_face_lookup(ob,psmd->dm,pa->num,pa->fuv,NULL);
00688         
00689         psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
00690         invert_m4_m4(imat,hairmat);
00691 
00692         sub_v3_v3v3(vec, nearest.co, key->co);
00693 
00694         if(point) {
00695             ekey = point->keys;
00696             point++;
00697         }
00698 
00699         for(k=0,key=pa->hair; k<pa->totkey; k++,key++) {
00700             add_v3_v3(key->co, vec);
00701             mul_m4_v3(imat,key->co);
00702 
00703             if(ekey) {
00704                 ekey->flag |= PEK_USE_WCO;
00705                 ekey++;
00706             }
00707         }
00708     }
00709 
00710     free_bvhtree_from_mesh(&bvhtree);
00711     dm->release(dm);
00712 
00713     psys_free_path_cache(psys, psys->edit);
00714 
00715     psys->flag &= ~PSYS_GLOBAL_HAIR;
00716 
00717     PE_update_object(scene, ob, 0);
00718 }
00719 
00720 static int connect_hair_exec(bContext *C, wmOperator *op)
00721 {
00722     Scene *scene= CTX_data_scene(C);
00723     Object *ob= ED_object_context(C);
00724     PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
00725     ParticleSystem *psys= NULL;
00726     int all = RNA_boolean_get(op->ptr, "all");
00727 
00728     if(!ob)
00729         return OPERATOR_CANCELLED;
00730 
00731     if(all) {
00732         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
00733             connect_hair(scene, ob, psys);
00734         }
00735     }
00736     else {
00737         psys = ptr.data;
00738         connect_hair(scene, ob, psys);
00739     }
00740 
00741     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00742     WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
00743 
00744     return OPERATOR_FINISHED;
00745 }
00746 
00747 void PARTICLE_OT_connect_hair(wmOperatorType *ot)
00748 {
00749     ot->name= "Connect Hair";
00750     ot->description= "Connect hair to the emitter mesh";
00751     ot->idname= "PARTICLE_OT_connect_hair";
00752     
00753     ot->exec= connect_hair_exec;
00754     
00755     /* flags */
00756     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00757 
00758     RNA_def_boolean(ot->srna, "all", 0, "All hair", "Connect all hair systems to the emitter mesh");
00759 }
00760