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