|
Blender
V2.59
|
00001 /* 00002 * $Id: transform_orientations.c 35242 2011-02-27 20:29:51Z jesterking $ 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 * Contributor(s): Martin Poirier 00021 * 00022 * ***** END GPL LICENSE BLOCK ***** 00023 */ 00024 00030 #include <string.h> 00031 #include <ctype.h> 00032 00033 #include "MEM_guardedalloc.h" 00034 00035 #include "DNA_armature_types.h" 00036 #include "DNA_curve_types.h" 00037 #include "DNA_object_types.h" 00038 #include "DNA_scene_types.h" 00039 #include "DNA_screen_types.h" 00040 #include "DNA_view3d_types.h" 00041 00042 00043 #include "BKE_armature.h" 00044 #include "BKE_context.h" 00045 #include "BKE_report.h" 00046 00047 #include "BLI_math.h" 00048 #include "BLI_blenlib.h" 00049 #include "BLI_editVert.h" 00050 #include "BLI_utildefines.h" 00051 00052 //#include "BIF_editmesh.h" 00053 //#include "BIF_interface.h" 00054 //#include "BIF_space.h" 00055 //#include "BIF_toolbox.h" 00056 00057 #include "ED_armature.h" 00058 #include "ED_mesh.h" 00059 #include "ED_curve.h" /* for ED_curve_editnurbs */ 00060 00061 00062 #include "RNA_define.h" 00063 00064 #include "transform.h" 00065 00066 /* *********************** TransSpace ************************** */ 00067 00068 void BIF_clearTransformOrientation(bContext *C) 00069 { 00070 View3D *v3d = CTX_wm_view3d(C); 00071 00072 ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces; 00073 BLI_freelistN(transform_spaces); 00074 00075 // Need to loop over all view3d 00076 if(v3d && v3d->twmode >= V3D_MANIP_CUSTOM) { 00077 v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */ 00078 } 00079 } 00080 00081 static TransformOrientation* findOrientationName(ListBase *lb, const char *name) 00082 { 00083 TransformOrientation *ts= NULL; 00084 00085 for (ts= lb->first; ts; ts = ts->next) { 00086 if (strncmp(ts->name, name, sizeof(ts->name)-1) == 0) { 00087 return ts; 00088 } 00089 } 00090 00091 return NULL; 00092 } 00093 00094 static int uniqueOrientationNameCheck(void *arg, const char *name) 00095 { 00096 return findOrientationName((ListBase *)arg, name) != NULL; 00097 } 00098 00099 static void uniqueOrientationName(ListBase *lb, char *name) 00100 { 00101 BLI_uniquename_cb(uniqueOrientationNameCheck, lb, "Space", '.', name, sizeof(((TransformOrientation *)NULL)->name)); 00102 } 00103 00104 void BIF_createTransformOrientation(bContext *C, ReportList *reports, char *name, int use, int overwrite) 00105 { 00106 Object *obedit = CTX_data_edit_object(C); 00107 Object *ob = CTX_data_active_object(C); 00108 TransformOrientation *ts = NULL; 00109 00110 if (obedit) { 00111 if (obedit->type == OB_MESH) 00112 ts = createMeshSpace(C, reports, name, overwrite); 00113 else if (obedit->type == OB_ARMATURE) 00114 ts = createBoneSpace(C, reports, name, overwrite); 00115 } 00116 else if (ob && (ob->mode & OB_MODE_POSE)) { 00117 ts = createBoneSpace(C, reports, name, overwrite); 00118 } 00119 else { 00120 ts = createObjectSpace(C, reports, name, overwrite); 00121 } 00122 00123 if (use && ts != NULL) 00124 { 00125 BIF_selectTransformOrientation(C, ts); 00126 } 00127 } 00128 00129 TransformOrientation *createObjectSpace(bContext *C, ReportList *UNUSED(reports), char *name, int overwrite) { 00130 Base *base = CTX_data_active_base(C); 00131 Object *ob; 00132 float mat[3][3]; 00133 00134 if (base == NULL) 00135 return NULL; 00136 00137 00138 ob = base->object; 00139 00140 copy_m3_m4(mat, ob->obmat); 00141 normalize_m3(mat); 00142 00143 /* use object name if no name is given */ 00144 if (name[0] == 0) 00145 { 00146 strncpy(name, ob->id.name+2, 35); 00147 } 00148 00149 return addMatrixSpace(C, mat, name, overwrite); 00150 } 00151 00152 TransformOrientation *createBoneSpace(bContext *C, ReportList *reports, char *name, int overwrite) { 00153 float mat[3][3]; 00154 float normal[3], plane[3]; 00155 00156 getTransformOrientation(C, normal, plane, 0); 00157 00158 if (createSpaceNormalTangent(mat, normal, plane) == 0) { 00159 BKE_reports_prepend(reports, "Cannot use zero-length bone"); 00160 return NULL; 00161 } 00162 00163 if (name[0] == 0) 00164 { 00165 strcpy(name, "Bone"); 00166 } 00167 00168 return addMatrixSpace(C, mat, name, overwrite); 00169 } 00170 00171 TransformOrientation *createMeshSpace(bContext *C, ReportList *reports, char *name, int overwrite) { 00172 float mat[3][3]; 00173 float normal[3], plane[3]; 00174 int type; 00175 00176 type = getTransformOrientation(C, normal, plane, 0); 00177 00178 switch (type) 00179 { 00180 case ORIENTATION_VERT: 00181 if (createSpaceNormal(mat, normal) == 0) { 00182 BKE_reports_prepend(reports, "Cannot use vertex with zero-length normal"); 00183 return NULL; 00184 } 00185 00186 if (name[0] == 0) 00187 { 00188 strcpy(name, "Vertex"); 00189 } 00190 break; 00191 case ORIENTATION_EDGE: 00192 if (createSpaceNormalTangent(mat, normal, plane) == 0) { 00193 BKE_reports_prepend(reports, "Cannot use zero-length edge"); 00194 return NULL; 00195 } 00196 00197 if (name[0] == 0) 00198 { 00199 strcpy(name, "Edge"); 00200 } 00201 break; 00202 case ORIENTATION_FACE: 00203 if (createSpaceNormalTangent(mat, normal, plane) == 0) { 00204 BKE_reports_prepend(reports, "Cannot use zero-area face"); 00205 return NULL; 00206 } 00207 00208 if (name[0] == 0) 00209 { 00210 strcpy(name, "Face"); 00211 } 00212 break; 00213 default: 00214 return NULL; 00215 break; 00216 } 00217 00218 return addMatrixSpace(C, mat, name, overwrite); 00219 } 00220 00221 int createSpaceNormal(float mat[3][3], float normal[3]) 00222 { 00223 float tangent[3] = {0.0f, 0.0f, 1.0f}; 00224 00225 VECCOPY(mat[2], normal); 00226 if (normalize_v3(mat[2]) == 0.0f) { 00227 return 0; /* error return */ 00228 } 00229 00230 cross_v3_v3v3(mat[0], mat[2], tangent); 00231 if (dot_v3v3(mat[0], mat[0]) == 0.0f) { 00232 tangent[0] = 1.0f; 00233 tangent[1] = tangent[2] = 0.0f; 00234 cross_v3_v3v3(mat[0], tangent, mat[2]); 00235 } 00236 00237 cross_v3_v3v3(mat[1], mat[2], mat[0]); 00238 00239 normalize_m3(mat); 00240 00241 return 1; 00242 } 00243 00244 int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]) 00245 { 00246 VECCOPY(mat[2], normal); 00247 if (normalize_v3(mat[2]) == 0.0f) { 00248 return 0; /* error return */ 00249 } 00250 00251 /* preempt zero length tangent from causing trouble */ 00252 if (tangent[0] == 0 && tangent[1] == 0 && tangent[2] == 0) 00253 { 00254 tangent[2] = 1; 00255 } 00256 00257 cross_v3_v3v3(mat[0], mat[2], tangent); 00258 if (normalize_v3(mat[0]) == 0.0f) { 00259 return 0; /* error return */ 00260 } 00261 00262 cross_v3_v3v3(mat[1], mat[2], mat[0]); 00263 00264 normalize_m3(mat); 00265 00266 return 1; 00267 } 00268 00269 TransformOrientation* addMatrixSpace(bContext *C, float mat[3][3], char name[], int overwrite) { 00270 ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces; 00271 TransformOrientation *ts = NULL; 00272 00273 if (overwrite) 00274 { 00275 ts = findOrientationName(transform_spaces, name); 00276 } 00277 else 00278 { 00279 uniqueOrientationName(transform_spaces, name); 00280 } 00281 00282 /* if not, create a new one */ 00283 if (ts == NULL) 00284 { 00285 ts = MEM_callocN(sizeof(TransformOrientation), "UserTransSpace from matrix"); 00286 BLI_addtail(transform_spaces, ts); 00287 strncpy(ts->name, name, 35); 00288 } 00289 00290 /* copy matrix into transform space */ 00291 copy_m3_m3(ts->mat, mat); 00292 00293 return ts; 00294 } 00295 00296 void BIF_removeTransformOrientation(bContext *C, TransformOrientation *target) { 00297 ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces; 00298 TransformOrientation *ts; 00299 int i; 00300 00301 for (i = 0, ts = transform_spaces->first; ts; ts = ts->next, i++) { 00302 if (ts == target) { 00303 View3D *v3d = CTX_wm_view3d(C); 00304 if(v3d) { 00305 int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM); 00306 00307 // Transform_fix_me NEED TO DO THIS FOR ALL VIEW3D 00308 if (selected_index == i) { 00309 v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */ 00310 } 00311 else if (selected_index > i) { 00312 v3d->twmode--; 00313 } 00314 00315 } 00316 00317 BLI_freelinkN(transform_spaces, ts); 00318 break; 00319 } 00320 } 00321 } 00322 00323 void BIF_removeTransformOrientationIndex(bContext *C, int index) { 00324 ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces; 00325 TransformOrientation *ts= BLI_findlink(transform_spaces, index); 00326 00327 if (ts) { 00328 View3D *v3d = CTX_wm_view3d(C); 00329 if(v3d) { 00330 int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM); 00331 00332 // Transform_fix_me NEED TO DO THIS FOR ALL VIEW3D 00333 if (selected_index == index) { 00334 v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */ 00335 } 00336 else if (selected_index > index) { 00337 v3d->twmode--; 00338 } 00339 00340 } 00341 00342 BLI_freelinkN(transform_spaces, ts); 00343 } 00344 } 00345 00346 void BIF_selectTransformOrientation(bContext *C, TransformOrientation *target) { 00347 ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces; 00348 View3D *v3d = CTX_wm_view3d(C); 00349 TransformOrientation *ts; 00350 int i; 00351 00352 for (i = 0, ts = transform_spaces->first; ts; ts = ts->next, i++) { 00353 if (ts == target) { 00354 v3d->twmode = V3D_MANIP_CUSTOM + i; 00355 break; 00356 } 00357 } 00358 } 00359 00360 void BIF_selectTransformOrientationValue(bContext *C, int orientation) { 00361 View3D *v3d = CTX_wm_view3d(C); 00362 if(v3d) /* currently using generic poll */ 00363 v3d->twmode = orientation; 00364 } 00365 00366 EnumPropertyItem *BIF_enumTransformOrientation(bContext *C) 00367 { 00368 Scene *scene; 00369 ListBase *transform_spaces; 00370 TransformOrientation *ts= NULL; 00371 00372 EnumPropertyItem global = {V3D_MANIP_GLOBAL, "GLOBAL", 0, "Global", ""}; 00373 EnumPropertyItem normal = {V3D_MANIP_NORMAL, "NORMAL", 0, "Normal", ""}; 00374 EnumPropertyItem local = {V3D_MANIP_LOCAL, "LOCAL", 0, "Local", ""}; 00375 EnumPropertyItem view = {V3D_MANIP_VIEW, "VIEW", 0, "View", ""}; 00376 EnumPropertyItem tmp = {0, "", 0, "", ""}; 00377 EnumPropertyItem *item= NULL; 00378 int i = V3D_MANIP_CUSTOM, totitem= 0; 00379 00380 RNA_enum_item_add(&item, &totitem, &global); 00381 RNA_enum_item_add(&item, &totitem, &normal); 00382 RNA_enum_item_add(&item, &totitem, &local); 00383 RNA_enum_item_add(&item, &totitem, &view); 00384 00385 if(C) { 00386 scene= CTX_data_scene(C); 00387 00388 if(scene) { 00389 transform_spaces = &scene->transform_spaces; 00390 ts = transform_spaces->first; 00391 } 00392 } 00393 00394 if(ts) 00395 RNA_enum_item_add_separator(&item, &totitem); 00396 00397 for(; ts; ts = ts->next) { 00398 tmp.identifier = "CUSTOM"; 00399 tmp.name= ts->name; 00400 tmp.value = i++; 00401 RNA_enum_item_add(&item, &totitem, &tmp); 00402 } 00403 00404 RNA_enum_item_end(&item, &totitem); 00405 00406 return item; 00407 } 00408 00409 const char * BIF_menustringTransformOrientation(const bContext *C, const char *title) { 00410 char menu[] = "%t|Global%x0|Local%x1|Gimbal%x4|Normal%x2|View%x3"; 00411 ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces; 00412 TransformOrientation *ts; 00413 int i = V3D_MANIP_CUSTOM; 00414 char *str_menu, *p; 00415 00416 00417 str_menu = MEM_callocN(strlen(menu) + strlen(title) + 1 + 40 * BIF_countTransformOrientation(C), "UserTransSpace from matrix"); 00418 p = str_menu; 00419 00420 p += sprintf(str_menu, "%s", title); 00421 p += sprintf(p, "%s", menu); 00422 00423 for (ts = transform_spaces->first; ts; ts = ts->next) { 00424 p += sprintf(p, "|%s%%x%d", ts->name, i++); 00425 } 00426 00427 return str_menu; 00428 } 00429 00430 int BIF_countTransformOrientation(const bContext *C) { 00431 ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces; 00432 TransformOrientation *ts; 00433 int count = 0; 00434 00435 for (ts = transform_spaces->first; ts; ts = ts->next) { 00436 count++; 00437 } 00438 00439 return count; 00440 } 00441 00442 void applyTransformOrientation(const bContext *C, float mat[3][3], char *name) { 00443 TransformOrientation *ts; 00444 View3D *v3d = CTX_wm_view3d(C); 00445 int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM); 00446 int i; 00447 00448 if (selected_index >= 0) { 00449 for (i = 0, ts = CTX_data_scene(C)->transform_spaces.first; ts; ts = ts->next, i++) { 00450 if (selected_index == i) { 00451 00452 if (name) 00453 strcpy(name, ts->name); 00454 00455 copy_m3_m3(mat, ts->mat); 00456 break; 00457 } 00458 } 00459 } 00460 } 00461 00462 static int count_bone_select(bArmature *arm, ListBase *lb, int do_it) 00463 { 00464 Bone *bone; 00465 int do_next; 00466 int total = 0; 00467 00468 for(bone= lb->first; bone; bone= bone->next) { 00469 bone->flag &= ~BONE_TRANSFORM; 00470 do_next = do_it; 00471 if(do_it) { 00472 if(bone->layer & arm->layer) { 00473 if (bone->flag & BONE_SELECTED) { 00474 bone->flag |= BONE_TRANSFORM; 00475 total++; 00476 do_next= 0; // no transform on children if one parent bone is selected 00477 } 00478 } 00479 } 00480 total += count_bone_select(arm, &bone->childbase, do_next); 00481 } 00482 00483 return total; 00484 } 00485 00486 void initTransformOrientation(bContext *C, TransInfo *t) 00487 { 00488 View3D *v3d = CTX_wm_view3d(C); 00489 Object *ob = CTX_data_active_object(C); 00490 Object *obedit = CTX_data_active_object(C); 00491 00492 switch(t->current_orientation) { 00493 case V3D_MANIP_GLOBAL: 00494 unit_m3(t->spacemtx); 00495 strcpy(t->spacename, "global"); 00496 break; 00497 00498 case V3D_MANIP_GIMBAL: 00499 unit_m3(t->spacemtx); 00500 if (gimbal_axis(ob, t->spacemtx)) { 00501 strcpy(t->spacename, "gimbal"); 00502 break; 00503 } 00504 /* no gimbal fallthrough to normal */ 00505 case V3D_MANIP_NORMAL: 00506 if(obedit || (ob && ob->mode & OB_MODE_POSE)) { 00507 strcpy(t->spacename, "normal"); 00508 ED_getTransformOrientationMatrix(C, t->spacemtx, (v3d->around == V3D_ACTIVE)); 00509 break; 00510 } 00511 /* no break we define 'normal' as 'local' in Object mode */ 00512 case V3D_MANIP_LOCAL: 00513 strcpy(t->spacename, "local"); 00514 00515 if(ob) { 00516 copy_m3_m4(t->spacemtx, ob->obmat); 00517 normalize_m3(t->spacemtx); 00518 } else { 00519 unit_m3(t->spacemtx); 00520 } 00521 00522 break; 00523 00524 case V3D_MANIP_VIEW: 00525 if (t->ar->regiontype == RGN_TYPE_WINDOW) 00526 { 00527 RegionView3D *rv3d = t->ar->regiondata; 00528 float mat[3][3]; 00529 00530 strcpy(t->spacename, "view"); 00531 copy_m3_m4(mat, rv3d->viewinv); 00532 normalize_m3(mat); 00533 copy_m3_m3(t->spacemtx, mat); 00534 } 00535 else 00536 { 00537 unit_m3(t->spacemtx); 00538 } 00539 break; 00540 default: /* V3D_MANIP_CUSTOM */ 00541 applyTransformOrientation(C, t->spacemtx, t->spacename); 00542 break; 00543 } 00544 } 00545 00546 int getTransformOrientation(const bContext *C, float normal[3], float plane[3], int activeOnly) 00547 { 00548 Scene *scene = CTX_data_scene(C); 00549 View3D *v3d = CTX_wm_view3d(C); 00550 Object *obedit= CTX_data_edit_object(C); 00551 Base *base; 00552 Object *ob = OBACT; 00553 int result = ORIENTATION_NONE; 00554 00555 normal[0] = normal[1] = normal[2] = 0; 00556 plane[0] = plane[1] = plane[2] = 0; 00557 00558 if(obedit) 00559 { 00560 float imat[3][3], mat[3][3]; 00561 00562 /* we need the transpose of the inverse for a normal... */ 00563 copy_m3_m4(imat, ob->obmat); 00564 00565 invert_m3_m3(mat, imat); 00566 transpose_m3(mat); 00567 00568 ob= obedit; 00569 00570 if(ob->type==OB_MESH) 00571 { 00572 Mesh *me= ob->data; 00573 EditMesh *em = me->edit_mesh; 00574 EditVert *eve; 00575 EditSelection ese; 00576 float vec[3]= {0,0,0}; 00577 00578 /* USE LAST SELECTED WITH ACTIVE */ 00579 if (activeOnly && EM_get_actSelection(em, &ese)) 00580 { 00581 EM_editselection_normal(normal, &ese); 00582 EM_editselection_plane(plane, &ese); 00583 00584 switch (ese.type) 00585 { 00586 case EDITVERT: 00587 result = ORIENTATION_VERT; 00588 break; 00589 case EDITEDGE: 00590 result = ORIENTATION_EDGE; 00591 break; 00592 case EDITFACE: 00593 result = ORIENTATION_FACE; 00594 break; 00595 } 00596 } 00597 else 00598 { 00599 if (em->totfacesel >= 1) 00600 { 00601 EditFace *efa; 00602 00603 for(efa= em->faces.first; efa; efa= efa->next) 00604 { 00605 if(efa->f & SELECT) 00606 { 00607 VECADD(normal, normal, efa->n); 00608 sub_v3_v3v3(vec, efa->v2->co, efa->v1->co); 00609 VECADD(plane, plane, vec); 00610 } 00611 } 00612 00613 result = ORIENTATION_FACE; 00614 } 00615 else if (em->totvertsel == 3) 00616 { 00617 EditVert *v1 = NULL, *v2 = NULL, *v3 = NULL; 00618 float cotangent[3]; 00619 00620 for (eve = em->verts.first; eve; eve = eve->next) 00621 { 00622 if ( eve->f & SELECT ) { 00623 if (v1 == NULL) { 00624 v1 = eve; 00625 } 00626 else if (v2 == NULL) { 00627 v2 = eve; 00628 } 00629 else { 00630 v3 = eve; 00631 00632 sub_v3_v3v3(plane, v2->co, v1->co); 00633 sub_v3_v3v3(cotangent, v3->co, v2->co); 00634 cross_v3_v3v3(normal, cotangent, plane); 00635 break; 00636 } 00637 } 00638 } 00639 00640 /* if there's an edge available, use that for the tangent */ 00641 if (em->totedgesel >= 1) 00642 { 00643 EditEdge *eed = NULL; 00644 00645 for(eed= em->edges.first; eed; eed= eed->next) { 00646 if(eed->f & SELECT) { 00647 sub_v3_v3v3(plane, eed->v2->co, eed->v1->co); 00648 break; 00649 } 00650 } 00651 } 00652 00653 result = ORIENTATION_FACE; 00654 } 00655 else if (em->totedgesel == 1) 00656 { 00657 EditEdge *eed; 00658 00659 for(eed= em->edges.first; eed; eed= eed->next) { 00660 if(eed->f & SELECT) { 00661 /* use average vert normals as plane and edge vector as normal */ 00662 VECCOPY(plane, eed->v1->no); 00663 VECADD(plane, plane, eed->v2->no); 00664 sub_v3_v3v3(normal, eed->v2->co, eed->v1->co); 00665 break; 00666 } 00667 } 00668 result = ORIENTATION_EDGE; 00669 } 00670 else if (em->totvertsel == 2) 00671 { 00672 EditVert *v1 = NULL, *v2 = NULL; 00673 00674 for (eve = em->verts.first; eve; eve = eve->next) 00675 { 00676 if ( eve->f & SELECT ) { 00677 if (v1 == NULL) { 00678 v1 = eve; 00679 } 00680 else { 00681 v2 = eve; 00682 00683 VECCOPY(plane, v1->no); 00684 VECADD(plane, plane, v2->no); 00685 sub_v3_v3v3(normal, v2->co, v1->co); 00686 break; 00687 } 00688 } 00689 } 00690 result = ORIENTATION_EDGE; 00691 } 00692 else if (em->totvertsel == 1) 00693 { 00694 for (eve = em->verts.first; eve; eve = eve->next) 00695 { 00696 if ( eve->f & SELECT ) { 00697 VECCOPY(normal, eve->no); 00698 break; 00699 } 00700 } 00701 result = ORIENTATION_VERT; 00702 } 00703 else if (em->totvertsel > 3) 00704 { 00705 normal[0] = normal[1] = normal[2] = 0; 00706 00707 for (eve = em->verts.first; eve; eve = eve->next) 00708 { 00709 if ( eve->f & SELECT ) { 00710 add_v3_v3(normal, eve->no); 00711 } 00712 } 00713 normalize_v3(normal); 00714 result = ORIENTATION_VERT; 00715 } 00716 } 00717 } /* end editmesh */ 00718 else if ELEM(obedit->type, OB_CURVE, OB_SURF) 00719 { 00720 Curve *cu= obedit->data; 00721 Nurb *nu; 00722 BezTriple *bezt; 00723 int a; 00724 ListBase *nurbs= ED_curve_editnurbs(cu); 00725 00726 for (nu = nurbs->first; nu; nu = nu->next) 00727 { 00728 /* only bezier has a normal */ 00729 if(nu->type == CU_BEZIER) 00730 { 00731 bezt= nu->bezt; 00732 a= nu->pntsu; 00733 while(a--) 00734 { 00735 /* exception */ 00736 if ( (bezt->f1 & SELECT) + (bezt->f2 & SELECT) + (bezt->f3 & SELECT) > SELECT ) 00737 { 00738 sub_v3_v3v3(normal, bezt->vec[0], bezt->vec[2]); 00739 } 00740 else 00741 { 00742 if(bezt->f1) 00743 { 00744 sub_v3_v3v3(normal, bezt->vec[0], bezt->vec[1]); 00745 } 00746 if(bezt->f2) 00747 { 00748 sub_v3_v3v3(normal, bezt->vec[0], bezt->vec[2]); 00749 } 00750 if(bezt->f3) 00751 { 00752 sub_v3_v3v3(normal, bezt->vec[1], bezt->vec[2]); 00753 } 00754 } 00755 bezt++; 00756 } 00757 } 00758 } 00759 00760 if (normal[0] != 0 || normal[1] != 0 || normal[2] != 0) 00761 { 00762 result = ORIENTATION_NORMAL; 00763 } 00764 } 00765 else if(obedit->type==OB_MBALL) 00766 { 00767 #if 0 // XXX 00768 /* editmball.c */ 00769 extern ListBase editelems; /* go away ! */ 00770 MetaElem *ml, *ml_sel = NULL; 00771 00772 /* loop and check that only one element is selected */ 00773 for (ml = editelems.first; ml; ml = ml->next) 00774 { 00775 if (ml->flag & SELECT) { 00776 if (ml_sel == NULL) 00777 { 00778 ml_sel = ml; 00779 } 00780 else 00781 { 00782 ml_sel = NULL; 00783 break; 00784 } 00785 } 00786 } 00787 00788 if (ml_sel) 00789 { 00790 float mat[4][4]; 00791 00792 /* Rotation of MetaElem is stored in quat */ 00793 quat_to_mat4( mat,ml_sel->quat); 00794 00795 VECCOPY(normal, mat[2]); 00796 00797 negate_v3_v3(plane, mat[1]); 00798 00799 result = ORIENTATION_NORMAL; 00800 } 00801 #endif 00802 00803 } 00804 else if (obedit->type == OB_ARMATURE) 00805 { 00806 bArmature *arm = obedit->data; 00807 EditBone *ebone; 00808 00809 for (ebone = arm->edbo->first; ebone; ebone=ebone->next) { 00810 if (arm->layer & ebone->layer) 00811 { 00812 if (ebone->flag & BONE_SELECTED) 00813 { 00814 float tmat[3][3]; 00815 float vec[3]; 00816 sub_v3_v3v3(vec, ebone->tail, ebone->head); 00817 normalize_v3(vec); 00818 add_v3_v3(normal, vec); 00819 00820 vec_roll_to_mat3(vec, ebone->roll, tmat); 00821 add_v3_v3(plane, tmat[2]); 00822 } 00823 } 00824 } 00825 00826 normalize_v3(normal); 00827 normalize_v3(plane); 00828 00829 if (plane[0] != 0 || plane[1] != 0 || plane[2] != 0) 00830 { 00831 result = ORIENTATION_EDGE; 00832 } 00833 00834 } 00835 00836 /* Vectors from edges don't need the special transpose inverse multiplication */ 00837 if (result == ORIENTATION_EDGE) 00838 { 00839 mul_mat3_m4_v3(ob->obmat, normal); 00840 mul_mat3_m4_v3(ob->obmat, plane); 00841 } 00842 else 00843 { 00844 mul_m3_v3(mat, normal); 00845 mul_m3_v3(mat, plane); 00846 } 00847 } 00848 else if(ob && (ob->mode & OB_MODE_POSE)) 00849 { 00850 bArmature *arm= ob->data; 00851 bPoseChannel *pchan; 00852 int totsel; 00853 00854 totsel = count_bone_select(arm, &arm->bonebase, 1); 00855 if(totsel) { 00856 float imat[3][3], mat[3][3]; 00857 00858 /* use channels to get stats */ 00859 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { 00860 if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) { 00861 add_v3_v3(normal, pchan->pose_mat[2]); 00862 add_v3_v3(plane, pchan->pose_mat[1]); 00863 } 00864 } 00865 negate_v3(plane); 00866 00867 /* we need the transpose of the inverse for a normal... */ 00868 copy_m3_m4(imat, ob->obmat); 00869 00870 invert_m3_m3(mat, imat); 00871 transpose_m3(mat); 00872 mul_m3_v3(mat, normal); 00873 mul_m3_v3(mat, plane); 00874 00875 result = ORIENTATION_EDGE; 00876 } 00877 } 00878 else if(ob && (ob->mode & (OB_MODE_ALL_PAINT|OB_MODE_PARTICLE_EDIT))) 00879 { 00880 } 00881 else { 00882 /* we need the one selected object, if its not active */ 00883 ob = OBACT; 00884 if(ob && !(ob->flag & SELECT)) ob = NULL; 00885 00886 for(base= scene->base.first; base; base= base->next) { 00887 if TESTBASELIB(v3d, base) { 00888 if(ob == NULL) { 00889 ob= base->object; 00890 break; 00891 } 00892 } 00893 } 00894 00895 if (ob) { 00896 VECCOPY(normal, ob->obmat[2]); 00897 VECCOPY(plane, ob->obmat[1]); 00898 } 00899 result = ORIENTATION_NORMAL; 00900 } 00901 00902 return result; 00903 } 00904 00905 void ED_getTransformOrientationMatrix(const bContext *C, float orientation_mat[][3], int activeOnly) 00906 { 00907 float normal[3]={0.0, 0.0, 0.0}; 00908 float plane[3]={0.0, 0.0, 0.0}; 00909 00910 int type; 00911 00912 type = getTransformOrientation(C, normal, plane, activeOnly); 00913 00914 switch (type) 00915 { 00916 case ORIENTATION_NORMAL: 00917 if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) 00918 { 00919 type = ORIENTATION_NONE; 00920 } 00921 break; 00922 case ORIENTATION_VERT: 00923 if (createSpaceNormal(orientation_mat, normal) == 0) 00924 { 00925 type = ORIENTATION_NONE; 00926 } 00927 break; 00928 case ORIENTATION_EDGE: 00929 if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) 00930 { 00931 type = ORIENTATION_NONE; 00932 } 00933 break; 00934 case ORIENTATION_FACE: 00935 if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) 00936 { 00937 type = ORIENTATION_NONE; 00938 } 00939 break; 00940 } 00941 00942 if (type == ORIENTATION_NONE) 00943 { 00944 unit_m3(orientation_mat); 00945 } 00946 }