Blender V2.61 - r43446
|
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