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) 2011 by Blender Foundation 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): Benoit Bolsee, 00024 * Nick Samarin 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00029 #include <math.h> 00030 00031 #include "MEM_guardedalloc.h" 00032 00033 #include "DNA_scene_types.h" 00034 #include "DNA_object_types.h" 00035 #include "DNA_meshdata_types.h" 00036 #include "DNA_modifier_types.h" 00037 #include "DNA_ID.h" 00038 00039 #include "BKE_library.h" 00040 #include "BKE_depsgraph.h" 00041 #include "BKE_context.h" 00042 #include "BKE_main.h" 00043 #include "BKE_mesh.h" 00044 #include "BKE_modifier.h" 00045 #include "BKE_scene.h" 00046 #include "BKE_DerivedMesh.h" 00047 #include "BKE_cdderivedmesh.h" 00048 #include "BKE_report.h" 00049 00050 #include "BLI_editVert.h" 00051 #include "BLI_listbase.h" 00052 #include "BLI_utildefines.h" 00053 #include "BLI_math_vector.h" 00054 #include "BLI_linklist.h" 00055 00056 #include "ED_object.h" 00057 #include "ED_mesh.h" 00058 #include "ED_screen.h" 00059 00060 #include "RNA_access.h" 00061 00062 #include "WM_api.h" 00063 #include "WM_types.h" 00064 00065 #include "mesh_intern.h" 00066 #include "recast-capi.h" 00067 00068 static void createVertsTrisData(bContext *C, LinkNode* obs, int *nverts_r, float **verts_r, int *ntris_r, int **tris_r) 00069 { 00070 MVert *mvert; 00071 int nfaces= 0, *tri, i, curnverts, basenverts, curnfaces; 00072 MFace *mface; 00073 float co[3], wco[3]; 00074 Object *ob; 00075 LinkNode *oblink, *dmlink; 00076 DerivedMesh *dm; 00077 Scene* scene= CTX_data_scene(C); 00078 LinkNode* dms= NULL; 00079 00080 int nverts, ntris, *tris; 00081 float *verts; 00082 00083 nverts= 0; 00084 ntris= 0; 00085 00086 /* calculate number of verts and tris */ 00087 for(oblink= obs; oblink; oblink= oblink->next) { 00088 ob= (Object*) oblink->link; 00089 dm= mesh_create_derived_no_virtual(scene, ob, NULL, CD_MASK_MESH); 00090 BLI_linklist_append(&dms, (void*)dm); 00091 00092 nverts+= dm->getNumVerts(dm); 00093 nfaces= dm->getNumFaces(dm); 00094 ntris+= nfaces; 00095 00096 /* resolve quad faces */ 00097 mface= dm->getFaceArray(dm); 00098 for(i= 0; i<nfaces; i++) { 00099 MFace* mf= &mface[i]; 00100 if(mf->v4) 00101 ntris+=1; 00102 } 00103 } 00104 00105 /* create data */ 00106 verts= MEM_mallocN(sizeof(float)*3*nverts, "createVertsTrisData verts"); 00107 tris= MEM_mallocN(sizeof(int)*3*ntris, "createVertsTrisData faces"); 00108 00109 basenverts= 0; 00110 tri= tris; 00111 for(oblink= obs, dmlink= dms; oblink && dmlink; 00112 oblink= oblink->next, dmlink= dmlink->next) { 00113 ob= (Object*) oblink->link; 00114 dm= (DerivedMesh*) dmlink->link; 00115 00116 curnverts= dm->getNumVerts(dm); 00117 mvert= dm->getVertArray(dm); 00118 00119 /* copy verts */ 00120 for(i= 0; i<curnverts; i++) { 00121 MVert *v= &mvert[i]; 00122 00123 copy_v3_v3(co, v->co); 00124 mul_v3_m4v3(wco, ob->obmat, co); 00125 00126 verts[3*(basenverts+i)+0]= wco[0]; 00127 verts[3*(basenverts+i)+1]= wco[2]; 00128 verts[3*(basenverts+i)+2]= wco[1]; 00129 } 00130 00131 /* create tris */ 00132 curnfaces= dm->getNumFaces(dm); 00133 mface= dm->getFaceArray(dm); 00134 00135 for(i= 0; i<curnfaces; i++) { 00136 MFace* mf= &mface[i]; 00137 00138 tri[0]= basenverts + mf->v1; 00139 tri[1]= basenverts + mf->v3; 00140 tri[2]= basenverts + mf->v2; 00141 tri += 3; 00142 00143 if(mf->v4) { 00144 tri[0]= basenverts + mf->v1; 00145 tri[1]= basenverts + mf->v4; 00146 tri[2]= basenverts + mf->v3; 00147 tri += 3; 00148 } 00149 } 00150 00151 basenverts+= curnverts; 00152 } 00153 00154 /* release derived mesh */ 00155 for(dmlink= dms; dmlink; dmlink= dmlink->next) { 00156 dm= (DerivedMesh*) dmlink->link; 00157 dm->release(dm); 00158 } 00159 00160 BLI_linklist_free(dms, NULL); 00161 00162 *nverts_r= nverts; 00163 *verts_r= verts; 00164 *ntris_r= ntris; 00165 *tris_r= tris; 00166 } 00167 00168 static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts, int ntris, int *tris, 00169 struct recast_polyMesh **pmesh, struct recast_polyMeshDetail **dmesh) 00170 { 00171 float bmin[3], bmax[3]; 00172 struct recast_heightfield *solid; 00173 unsigned char *triflags; 00174 struct recast_compactHeightfield* chf; 00175 struct recast_contourSet *cset; 00176 int width, height, walkableHeight, walkableClimb, walkableRadius; 00177 int minRegionArea, mergeRegionArea, maxEdgeLen; 00178 float detailSampleDist, detailSampleMaxError; 00179 00180 recast_calcBounds(verts, nverts, bmin, bmax); 00181 00182 /* ** Step 1. Initialize build config ** */ 00183 walkableHeight= (int)ceilf(recastParams->agentheight/ recastParams->cellheight); 00184 walkableClimb= (int)floorf(recastParams->agentmaxclimb / recastParams->cellheight); 00185 walkableRadius= (int)ceilf(recastParams->agentradius / recastParams->cellsize); 00186 minRegionArea= (int)(recastParams->regionminsize * recastParams->regionminsize); 00187 mergeRegionArea= (int)(recastParams->regionmergesize * recastParams->regionmergesize); 00188 maxEdgeLen= (int)(recastParams->edgemaxlen/recastParams->cellsize); 00189 detailSampleDist= recastParams->detailsampledist< 0.9f ? 0 : 00190 recastParams->cellsize * recastParams->detailsampledist; 00191 detailSampleMaxError= recastParams->cellheight * recastParams->detailsamplemaxerror; 00192 00193 /* Set the area where the navigation will be build. */ 00194 recast_calcGridSize(bmin, bmax, recastParams->cellsize, &width, &height); 00195 00196 /* ** Step 2: Rasterize input polygon soup ** */ 00197 /* Allocate voxel heightfield where we rasterize our input data to */ 00198 solid= recast_newHeightfield(); 00199 00200 if(!recast_createHeightfield(solid, width, height, bmin, bmax, recastParams->cellsize, recastParams->cellheight)) { 00201 recast_destroyHeightfield(solid); 00202 00203 return 0; 00204 } 00205 00206 /* Allocate array that can hold triangle flags */ 00207 triflags= MEM_callocN(sizeof(unsigned char)*ntris, "buildNavMesh triflags"); 00208 00209 /* Find triangles which are walkable based on their slope and rasterize them */ 00210 recast_markWalkableTriangles(RAD2DEG(recastParams->agentmaxslope), verts, nverts, tris, ntris, triflags); 00211 recast_rasterizeTriangles(verts, nverts, tris, triflags, ntris, solid); 00212 MEM_freeN(triflags); 00213 00214 /* ** Step 3: Filter walkables surfaces ** */ 00215 recast_filterLowHangingWalkableObstacles(walkableClimb, solid); 00216 recast_filterLedgeSpans(walkableHeight, walkableClimb, solid); 00217 recast_filterWalkableLowHeightSpans(walkableHeight, solid); 00218 00219 /* ** Step 4: Partition walkable surface to simple regions ** */ 00220 00221 chf= recast_newCompactHeightfield(); 00222 if(!recast_buildCompactHeightfield(walkableHeight, walkableClimb, solid, chf)) { 00223 recast_destroyHeightfield(solid); 00224 recast_destroyCompactHeightfield(chf); 00225 00226 return 0; 00227 } 00228 00229 recast_destroyHeightfield(solid); 00230 solid = NULL; 00231 00232 if (!recast_erodeWalkableArea(walkableRadius, chf)) { 00233 recast_destroyCompactHeightfield(chf); 00234 00235 return 0; 00236 } 00237 00238 /* Prepare for region partitioning, by calculating distance field along the walkable surface */ 00239 if(!recast_buildDistanceField(chf)) { 00240 recast_destroyCompactHeightfield(chf); 00241 00242 return 0; 00243 } 00244 00245 /* Partition the walkable surface into simple regions without holes */ 00246 if(!recast_buildRegions(chf, 0, minRegionArea, mergeRegionArea)) { 00247 recast_destroyCompactHeightfield(chf); 00248 00249 return 0; 00250 } 00251 00252 /* ** Step 5: Trace and simplify region contours ** */ 00253 /* Create contours */ 00254 cset= recast_newContourSet(); 00255 00256 if(!recast_buildContours(chf, recastParams->edgemaxerror, maxEdgeLen, cset)) { 00257 recast_destroyCompactHeightfield(chf); 00258 recast_destroyContourSet(cset); 00259 00260 return 0; 00261 } 00262 00263 /* ** Step 6: Build polygons mesh from contours ** */ 00264 *pmesh= recast_newPolyMesh(); 00265 if(!recast_buildPolyMesh(cset, recastParams->vertsperpoly, *pmesh)) { 00266 recast_destroyCompactHeightfield(chf); 00267 recast_destroyContourSet(cset); 00268 recast_destroyPolyMesh(*pmesh); 00269 00270 return 0; 00271 } 00272 00273 00274 /* ** Step 7: Create detail mesh which allows to access approximate height on each polygon ** */ 00275 00276 *dmesh= recast_newPolyMeshDetail(); 00277 if(!recast_buildPolyMeshDetail(*pmesh, chf, detailSampleDist, detailSampleMaxError, *dmesh)) { 00278 recast_destroyCompactHeightfield(chf); 00279 recast_destroyContourSet(cset); 00280 recast_destroyPolyMesh(*pmesh); 00281 recast_destroyPolyMeshDetail(*dmesh); 00282 00283 return 0; 00284 } 00285 00286 recast_destroyCompactHeightfield(chf); 00287 recast_destroyContourSet(cset); 00288 00289 return 1; 00290 } 00291 00292 static Object* createRepresentation(bContext *C, struct recast_polyMesh *pmesh, struct recast_polyMeshDetail *dmesh, Base* base) 00293 { 00294 float co[3], rot[3]; 00295 EditMesh *em; 00296 int i,j, k; 00297 unsigned short* v; 00298 int face[3]; 00299 Scene *scene= CTX_data_scene(C); 00300 Object* obedit; 00301 int createob= base==NULL; 00302 int nverts, nmeshes, nvp; 00303 unsigned short *verts, *polys; 00304 unsigned int *meshes; 00305 float bmin[3], cs, ch, *dverts; 00306 unsigned char *tris; 00307 00308 zero_v3(co); 00309 zero_v3(rot); 00310 00311 if(createob) { 00312 /* create new object */ 00313 obedit= ED_object_add_type(C, OB_MESH, co, rot, FALSE, 1); 00314 } 00315 else { 00316 obedit= base->object; 00317 scene_select_base(scene, base); 00318 copy_v3_v3(obedit->loc, co); 00319 copy_v3_v3(obedit->rot, rot); 00320 } 00321 00322 ED_object_enter_editmode(C, EM_DO_UNDO|EM_IGNORE_LAYER); 00323 em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); 00324 00325 if(!createob) { 00326 /* clear */ 00327 if(em->verts.first) free_vertlist(em, &em->verts); 00328 if(em->edges.first) free_edgelist(em, &em->edges); 00329 if(em->faces.first) free_facelist(em, &em->faces); 00330 if(em->selected.first) BLI_freelistN(&(em->selected)); 00331 } 00332 00333 /* create verts for polygon mesh */ 00334 verts= recast_polyMeshGetVerts(pmesh, &nverts); 00335 recast_polyMeshGetBoundbox(pmesh, bmin, NULL); 00336 recast_polyMeshGetCell(pmesh, &cs, &ch); 00337 00338 for(i= 0; i<nverts; i++) { 00339 v= &verts[3*i]; 00340 co[0]= bmin[0] + v[0]*cs; 00341 co[1]= bmin[1] + v[1]*ch; 00342 co[2]= bmin[2] + v[2]*cs; 00343 SWAP(float, co[1], co[2]); 00344 addvertlist(em, co, NULL); 00345 } 00346 00347 /* create custom data layer to save polygon idx */ 00348 CustomData_add_layer_named(&em->fdata, CD_RECAST, CD_CALLOC, NULL, 0, "createRepresentation recastData"); 00349 00350 /* create verts and faces for detailed mesh */ 00351 meshes= recast_polyMeshDetailGetMeshes(dmesh, &nmeshes); 00352 polys= recast_polyMeshGetPolys(pmesh, NULL, &nvp); 00353 dverts= recast_polyMeshDetailGetVerts(dmesh, NULL); 00354 tris= recast_polyMeshDetailGetTris(dmesh, NULL); 00355 00356 for(i= 0; i<nmeshes; i++) { 00357 int uniquevbase= em->totvert; 00358 unsigned int vbase= meshes[4*i+0]; 00359 unsigned short ndv= meshes[4*i+1]; 00360 unsigned short tribase= meshes[4*i+2]; 00361 unsigned short trinum= meshes[4*i+3]; 00362 const unsigned short* p= &polys[i*nvp*2]; 00363 int nv= 0; 00364 00365 for(j= 0; j < nvp; ++j) { 00366 if(p[j]==0xffff) break; 00367 nv++; 00368 } 00369 00370 /* create unique verts */ 00371 for(j= nv; j<ndv; j++) { 00372 copy_v3_v3(co, &dverts[3*(vbase + j)]); 00373 SWAP(float, co[1], co[2]); 00374 addvertlist(em, co, NULL); 00375 } 00376 00377 EM_init_index_arrays(em, 1, 0, 0); 00378 00379 /* create faces */ 00380 for(j= 0; j<trinum; j++) { 00381 unsigned char* tri= &tris[4*(tribase+j)]; 00382 EditFace* newFace; 00383 int* polygonIdx; 00384 00385 for(k= 0; k<3; k++) { 00386 if(tri[k]<nv) 00387 face[k]= p[tri[k]]; /* shared vertex */ 00388 else 00389 face[k]= uniquevbase+tri[k]-nv; /* unique vertex */ 00390 } 00391 newFace= addfacelist(em, EM_get_vert_for_index(face[0]), EM_get_vert_for_index(face[2]), 00392 EM_get_vert_for_index(face[1]), NULL, NULL, NULL); 00393 00394 /* set navigation polygon idx to the custom layer */ 00395 polygonIdx= (int*)CustomData_em_get(&em->fdata, newFace->data, CD_RECAST); 00396 *polygonIdx= i+1; /* add 1 to avoid zero idx */ 00397 } 00398 00399 EM_free_index_arrays(); 00400 } 00401 00402 recast_destroyPolyMesh(pmesh); 00403 recast_destroyPolyMeshDetail(dmesh); 00404 00405 BKE_mesh_end_editmesh((Mesh*)obedit->data, em); 00406 00407 DAG_id_tag_update((ID*)obedit->data, OB_RECALC_DATA); 00408 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 00409 00410 00411 ED_object_exit_editmode(C, EM_FREEDATA); 00412 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit); 00413 00414 if(createob) { 00415 obedit->gameflag&= ~OB_COLLISION; 00416 obedit->gameflag|= OB_NAVMESH; 00417 obedit->body_type= OB_BODY_TYPE_NAVMESH; 00418 rename_id((ID *)obedit, "Navmesh"); 00419 } 00420 00421 BKE_mesh_ensure_navmesh(obedit->data); 00422 00423 return obedit; 00424 } 00425 00426 static int create_navmesh_exec(bContext *C, wmOperator *op) 00427 { 00428 Scene* scene= CTX_data_scene(C); 00429 LinkNode* obs= NULL; 00430 Base* navmeshBase= NULL; 00431 00432 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { 00433 if (base->object->type == OB_MESH) { 00434 if (base->object->body_type==OB_BODY_TYPE_NAVMESH) { 00435 if (!navmeshBase || base == scene->basact) { 00436 navmeshBase= base; 00437 } 00438 } 00439 else { 00440 BLI_linklist_append(&obs, (void*)base->object); 00441 } 00442 } 00443 } 00444 CTX_DATA_END; 00445 00446 if (obs) { 00447 struct recast_polyMesh *pmesh= NULL; 00448 struct recast_polyMeshDetail *dmesh= NULL; 00449 00450 int nverts= 0, ntris= 0; 00451 int *tris= 0; 00452 float *verts= NULL; 00453 00454 createVertsTrisData(C, obs, &nverts, &verts, &ntris, &tris); 00455 BLI_linklist_free(obs, NULL); 00456 buildNavMesh(&scene->gm.recastData, nverts, verts, ntris, tris, &pmesh, &dmesh); 00457 createRepresentation(C, pmesh, dmesh, navmeshBase); 00458 00459 MEM_freeN(verts); 00460 MEM_freeN(tris); 00461 00462 return OPERATOR_FINISHED; 00463 } 00464 else { 00465 BKE_report(op->reports, RPT_ERROR, "No mesh objects found"); 00466 00467 return OPERATOR_CANCELLED; 00468 } 00469 } 00470 00471 void MESH_OT_navmesh_make(wmOperatorType *ot) 00472 { 00473 /* identifiers */ 00474 ot->name= "Create navigation mesh"; 00475 ot->description= "Create navigation mesh for selected objects"; 00476 ot->idname= "MESH_OT_navmesh_make"; 00477 00478 /* api callbacks */ 00479 ot->exec= create_navmesh_exec; 00480 00481 /* flags */ 00482 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00483 } 00484 00485 static int navmesh_face_copy_exec(bContext *C, wmOperator *op) 00486 { 00487 Object *obedit= CTX_data_edit_object(C); 00488 EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); 00489 00490 /* do work here */ 00491 EditFace *efa_act= EM_get_actFace(em, 0); 00492 00493 if(efa_act) { 00494 if(CustomData_has_layer(&em->fdata, CD_RECAST)) { 00495 EditFace *efa; 00496 int targetPolyIdx= *(int*)CustomData_em_get(&em->fdata, efa_act->data, CD_RECAST); 00497 targetPolyIdx= targetPolyIdx>=0? targetPolyIdx : -targetPolyIdx; 00498 00499 if(targetPolyIdx > 0) { 00500 /* set target poly idx to other selected faces */ 00501 for (efa= (EditFace *)em->faces.first; efa; efa= efa->next) { 00502 if((efa->f & SELECT) && efa != efa_act) { 00503 int* recastDataBlock= (int*)CustomData_em_get(&em->fdata, efa->data, CD_RECAST); 00504 *recastDataBlock= targetPolyIdx; 00505 } 00506 } 00507 } 00508 else { 00509 BKE_report(op->reports, RPT_ERROR, "Active face has no index set"); 00510 } 00511 } 00512 } 00513 00514 DAG_id_tag_update((ID*)obedit->data, OB_RECALC_DATA); 00515 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 00516 00517 BKE_mesh_end_editmesh((Mesh*)obedit->data, em); 00518 00519 return OPERATOR_FINISHED; 00520 } 00521 00522 void MESH_OT_navmesh_face_copy(struct wmOperatorType *ot) 00523 { 00524 /* identifiers */ 00525 ot->name= "NavMesh Copy Face Index"; 00526 ot->description= "Copy the index from the active face"; 00527 ot->idname= "MESH_OT_navmesh_face_copy"; 00528 00529 /* api callbacks */ 00530 ot->poll= ED_operator_editmesh; 00531 ot->exec= navmesh_face_copy_exec; 00532 00533 /* flags */ 00534 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00535 } 00536 00537 static int compare(const void * a, const void * b) 00538 { 00539 return ( *(int*)a - *(int*)b ); 00540 } 00541 00542 static int findFreeNavPolyIndex(EditMesh* em) 00543 { 00544 /* construct vector of indices */ 00545 int numfaces= em->totface; 00546 int* indices= MEM_callocN(sizeof(int)*numfaces, "findFreeNavPolyIndex(indices)"); 00547 EditFace* ef= (EditFace*)em->faces.last; 00548 int i, idx= 0, freeIdx= 1; 00549 00550 while(ef) { 00551 int polyIdx= *(int*)CustomData_em_get(&em->fdata, ef->data, CD_RECAST); 00552 indices[idx]= polyIdx; 00553 idx++; 00554 ef= ef->prev; 00555 } 00556 00557 qsort(indices, numfaces, sizeof(int), compare); 00558 00559 /* search first free index */ 00560 freeIdx= 1; 00561 for(i= 0; i<numfaces; i++) { 00562 if(indices[i]==freeIdx) 00563 freeIdx++; 00564 else if(indices[i]>freeIdx) 00565 break; 00566 } 00567 00568 MEM_freeN(indices); 00569 00570 return freeIdx; 00571 } 00572 00573 static int navmesh_face_add_exec(bContext *C, wmOperator *UNUSED(op)) 00574 { 00575 Object *obedit= CTX_data_edit_object(C); 00576 EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); 00577 EditFace *ef; 00578 00579 if(CustomData_has_layer(&em->fdata, CD_RECAST)) { 00580 int targetPolyIdx= findFreeNavPolyIndex(em); 00581 00582 if(targetPolyIdx>0) { 00583 /* set target poly idx to selected faces */ 00584 ef= (EditFace*)em->faces.last; 00585 while(ef) { 00586 if(ef->f & SELECT) { 00587 int *recastDataBlock= (int*)CustomData_em_get(&em->fdata, ef->data, CD_RECAST); 00588 *recastDataBlock= targetPolyIdx; 00589 } 00590 ef= ef->prev; 00591 } 00592 } 00593 } 00594 00595 DAG_id_tag_update((ID*)obedit->data, OB_RECALC_DATA); 00596 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 00597 00598 BKE_mesh_end_editmesh((Mesh*)obedit->data, em); 00599 return OPERATOR_FINISHED; 00600 } 00601 00602 void MESH_OT_navmesh_face_add(struct wmOperatorType *ot) 00603 { 00604 /* identifiers */ 00605 ot->name= "NavMesh New Face Index"; 00606 ot->description= "Add a new index and assign it to selected faces"; 00607 ot->idname= "MESH_OT_navmesh_face_add"; 00608 00609 /* api callbacks */ 00610 ot->poll= ED_operator_editmesh; 00611 ot->exec= navmesh_face_add_exec; 00612 00613 /* flags */ 00614 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00615 } 00616 00617 static int navmesh_obmode_data_poll(bContext *C) 00618 { 00619 Object *ob = ED_object_active_context(C); 00620 if (ob && (ob->mode == OB_MODE_OBJECT) && (ob->type == OB_MESH)) { 00621 Mesh *me= ob->data; 00622 return CustomData_has_layer(&me->fdata, CD_RECAST); 00623 } 00624 return FALSE; 00625 } 00626 00627 static int navmesh_obmode_poll(bContext *C) 00628 { 00629 Object *ob = ED_object_active_context(C); 00630 if (ob && (ob->mode == OB_MODE_OBJECT) && (ob->type == OB_MESH)) { 00631 return TRUE; 00632 } 00633 return FALSE; 00634 } 00635 00636 static int navmesh_reset_exec(bContext *C, wmOperator *UNUSED(op)) 00637 { 00638 Object *ob = ED_object_active_context(C); 00639 Mesh *me= ob->data; 00640 00641 CustomData_free_layers(&me->fdata, CD_RECAST, me->totface); 00642 00643 BKE_mesh_ensure_navmesh(me); 00644 00645 DAG_id_tag_update(&me->id, OB_RECALC_DATA); 00646 WM_event_add_notifier(C, NC_GEOM|ND_DATA, &me->id); 00647 00648 return OPERATOR_FINISHED; 00649 } 00650 00651 void MESH_OT_navmesh_reset(struct wmOperatorType *ot) 00652 { 00653 /* identifiers */ 00654 ot->name= "NavMesh Reset Index Values"; 00655 ot->description= "Assign a new index to every face"; 00656 ot->idname= "MESH_OT_navmesh_reset"; 00657 00658 /* api callbacks */ 00659 ot->poll= navmesh_obmode_poll; 00660 ot->exec= navmesh_reset_exec; 00661 00662 /* flags */ 00663 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00664 } 00665 00666 static int navmesh_clear_exec(bContext *C, wmOperator *UNUSED(op)) 00667 { 00668 Object *ob = ED_object_active_context(C); 00669 Mesh *me= ob->data; 00670 00671 CustomData_free_layers(&me->fdata, CD_RECAST, me->totface); 00672 00673 DAG_id_tag_update(&me->id, OB_RECALC_DATA); 00674 WM_event_add_notifier(C, NC_GEOM|ND_DATA, &me->id); 00675 00676 return OPERATOR_FINISHED; 00677 } 00678 00679 void MESH_OT_navmesh_clear(struct wmOperatorType *ot) 00680 { 00681 /* identifiers */ 00682 ot->name= "NavMesh Clear Data"; 00683 ot->description= "Remove navmesh data from this mesh"; 00684 ot->idname= "MESH_OT_navmesh_clear"; 00685 00686 /* api callbacks */ 00687 ot->poll= navmesh_obmode_data_poll; 00688 ot->exec= navmesh_clear_exec; 00689 00690 /* flags */ 00691 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00692 }