== Transform Orientations ==
Merge Normal orientation calculations with Custom Orientations, to make it work the same all accross the table: - One or more faces: use average face normal (first edge of faces define tangent) - One edge: use edge itself as normal (vertex normals define tangent) - One vertex: use vertex normal (tangent is perpendicular to normal and z-axis) - Two vertices => edge orientation - Two vertices => face orientation *I tested quite a bit but please report any bugs this might have caused.* ADDED FILE WARNING: source/blender/src/transform_orientations.c
This commit is contained in:
@@ -481,6 +481,17 @@ int addMatrixSpace(float mat[3][3], char name[]);
|
||||
int addObjectSpace(struct Object *ob);
|
||||
void applyTransformOrientation(void);
|
||||
|
||||
|
||||
#define ORIENTATION_NONE 0
|
||||
#define ORIENTATION_NORMAL 1
|
||||
#define ORIENTATION_VERT 2
|
||||
#define ORIENTATION_EDGE 3
|
||||
#define ORIENTATION_FACE 4
|
||||
|
||||
int getTransformOrientation(float normal[3], float plane[3], int activeOnly);
|
||||
int createSpaceNormal(float mat[3][3], float normal[3]);
|
||||
int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -57,8 +57,6 @@
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h" /* PET modes */
|
||||
#include "DNA_screen_types.h" /* area dimensions */
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_texture_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
@@ -158,584 +156,7 @@ static void helpline(TransInfo *t, float *vec)
|
||||
}
|
||||
}
|
||||
|
||||
/* *********************** TransSpace ************************** */
|
||||
|
||||
void BIF_clearTransformOrientation(void)
|
||||
{
|
||||
ListBase *transform_spaces = &G.scene->transform_spaces;
|
||||
BLI_freelistN(transform_spaces);
|
||||
|
||||
if (G.vd->twmode >= V3D_MANIP_CUSTOM)
|
||||
G.vd->twmode = V3D_MANIP_GLOBAL; /* fallback to global */
|
||||
}
|
||||
|
||||
void BIF_manageTransformOrientation(int confirm, int set) {
|
||||
int index = -1;
|
||||
|
||||
if (G.obedit) {
|
||||
if (G.obedit->type == OB_MESH)
|
||||
index = manageMeshSpace(confirm, set);
|
||||
}
|
||||
else {
|
||||
index = manageObjectSpace(confirm, set);
|
||||
}
|
||||
|
||||
if (set && index != -1)
|
||||
{
|
||||
BIF_selectTransformOrientationFromIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
int manageObjectSpace(int confirm, int set) {
|
||||
Base *base = BASACT;
|
||||
|
||||
if (base == NULL)
|
||||
return -1;
|
||||
|
||||
if (confirm == 0) {
|
||||
if (set && pupmenu("Custom Orientation %t|Add and Use Active Object%x1") != 1) {
|
||||
return -1;
|
||||
}
|
||||
else if (set == 0 && pupmenu("Custom Orientation %t|Add Active Object%x1") != 1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return addObjectSpace(base->object);
|
||||
}
|
||||
|
||||
/* return 1 on confirm */
|
||||
int confirmSpace(int set, char text[])
|
||||
{
|
||||
char menu[64];
|
||||
|
||||
if (set) {
|
||||
sprintf(menu, "Custom Orientation %%t|Add and Use %s%%x1", text);
|
||||
}
|
||||
else {
|
||||
sprintf(menu, "Custom Orientation %%t|Add %s%%x1", text);
|
||||
}
|
||||
|
||||
if (pupmenu(menu) == 1) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int manageMeshSpace(int confirm, int set) {
|
||||
EditMesh *em = G.editMesh;
|
||||
float mat[3][3];
|
||||
char name[36] = "";
|
||||
int index;
|
||||
|
||||
/* Vertice Selected */
|
||||
if (G.scene->selectmode & SCE_SELECT_VERTEX && (G.totvertsel == 1 || G.totvertsel == 2 || G.totvertsel == 3)) {
|
||||
if (G.totvertsel == 1) {
|
||||
/* EditSelection *ese; */
|
||||
EditVert *eve = NULL;
|
||||
float normal[3];
|
||||
|
||||
/*
|
||||
for (ese = em->selected.first; ese; ese = ese->next)
|
||||
{
|
||||
if ( ese->type == EDITVERT ) {
|
||||
eve = (EditVert *)ese->data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
for (eve = em->verts.first; eve; eve = eve->next)
|
||||
{
|
||||
if (eve->f & SELECT)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (eve == NULL)
|
||||
return -1;
|
||||
|
||||
if (confirm == 0 && confirmSpace(set, "vertex") == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
VECCOPY(normal, eve->no);
|
||||
Mat4Mul3Vecfl(G.obedit->obmat, normal);
|
||||
|
||||
if (createSpaceNormal(mat, normal) == 0) {
|
||||
error("Cannot use vertex with zero-length normal");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(name, "Vertex");
|
||||
}
|
||||
else if (G.totvertsel == 2) {
|
||||
/* EditSelection *ese; */
|
||||
EditVert *eve;
|
||||
EditVert *v1 = NULL, *v2 = NULL;
|
||||
float normal[3];
|
||||
|
||||
/*
|
||||
for (ese = em->selected.first; ese; ese = ese->next)
|
||||
{
|
||||
if ( ese->type == EDITVERT ) {
|
||||
if (v1 == NULL) {
|
||||
v1 = (EditVert *)ese->data;
|
||||
}
|
||||
else {
|
||||
v2 = (EditVert *)ese->data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
for (eve = em->verts.first; eve; eve = eve->next)
|
||||
{
|
||||
if ( eve->f & SELECT ) {
|
||||
if (v1 == NULL) {
|
||||
v1 = eve;
|
||||
}
|
||||
else {
|
||||
v2 = eve;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (v2 == NULL)
|
||||
return -1;
|
||||
|
||||
if (confirm == 0 && confirmSpace(set, "Edge") == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
VecSubf(normal, v2->co, v1->co);
|
||||
Mat4Mul3Vecfl(G.obedit->obmat, normal);
|
||||
|
||||
if (createSpaceNormal(mat, normal) == 0) {
|
||||
error("Cannot use zero-length edge");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(name, "Edge");
|
||||
}
|
||||
else if (G.totvertsel == 3) {
|
||||
/* EditSelection *ese; */
|
||||
EditVert *eve;
|
||||
EditVert *v1 = NULL, *v2 = NULL, *v3 = NULL;
|
||||
float normal[3], tangent[3], cotangent[3];
|
||||
|
||||
/*
|
||||
for (ese = em->selected.first; ese; ese = ese->next)
|
||||
{
|
||||
if ( ese->type == EDITVERT ) {
|
||||
if (v1 == NULL) {
|
||||
v1 = (EditVert *)ese->data;
|
||||
}
|
||||
else if (v2 == NULL) {
|
||||
v2 = (EditVert *)ese->data;
|
||||
}
|
||||
else {
|
||||
v3 = (EditVert *)ese->data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
for (eve = em->verts.first; eve; eve = eve->next)
|
||||
{
|
||||
if ( eve->f & SELECT ) {
|
||||
if (v1 == NULL) {
|
||||
v1 = eve;
|
||||
}
|
||||
else if (v2 == NULL) {
|
||||
v2 = eve;
|
||||
}
|
||||
else {
|
||||
v3 = eve;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (v3 == NULL)
|
||||
return -1;
|
||||
|
||||
if (confirm == 0 && confirmSpace(set, "Face") == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
VecSubf(tangent, v2->co, v1->co);
|
||||
VecSubf(cotangent, v3->co, v2->co);
|
||||
Crossf(normal, cotangent, tangent);
|
||||
|
||||
Mat4Mul3Vecfl(G.obedit->obmat, normal);
|
||||
Mat4Mul3Vecfl(G.obedit->obmat, tangent);
|
||||
|
||||
if (createSpaceNormal(mat, normal) == 0) {
|
||||
error("Cannot use zero-area face");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(name, "Face");
|
||||
}
|
||||
|
||||
}
|
||||
/* Edge Selected */
|
||||
else if(G.scene->selectmode & SCE_SELECT_EDGE && (G.totedgesel == 1 || G.totedgesel == 2)) {
|
||||
if (G.totedgesel == 1) {
|
||||
/* EditSelection *ese; */
|
||||
EditEdge *eed = NULL;
|
||||
float normal[3];
|
||||
|
||||
/*
|
||||
for (ese = em->selected.first; ese; ese = ese->next)
|
||||
{
|
||||
if ( ese->type == EDITEDGE ) {
|
||||
eed = (EditEdge *)ese->data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
for (eed = em->edges.first; eed; eed = eed->next)
|
||||
{
|
||||
if ( eed->f & SELECT ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (eed == NULL)
|
||||
return -1;
|
||||
|
||||
if (confirm == 0 && confirmSpace(set, "Edge") == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
VecSubf(normal, eed->v2->co, eed->v1->co);
|
||||
Mat4Mul3Vecfl(G.obedit->obmat, normal);
|
||||
|
||||
if (createSpaceNormal(mat, normal) == 0) {
|
||||
error("Cannot use zero-length edge");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(name, "Edge");
|
||||
}
|
||||
/* If selected edges form a triangle */
|
||||
else if (G.totedgesel == 2 && G.totvertsel == 3) {
|
||||
/* EditSelection *ese; */
|
||||
EditEdge *eed;
|
||||
EditEdge *e1 = NULL, *e2 = NULL;
|
||||
EditVert *v1 = NULL, *v2 = NULL, *v3 = NULL;
|
||||
float normal[3], tangent[3], cotangent[3];
|
||||
|
||||
/*
|
||||
for (ese = em->selected.first; ese; ese = ese->next)
|
||||
{
|
||||
if ( ese->type == EDITEDGE ) {
|
||||
if (e1 == NULL) {
|
||||
e1 = (EditEdge *)ese->data;
|
||||
}
|
||||
else {
|
||||
e2 = (EditEdge *)ese->data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
for (eed = em->edges.first; eed; eed = eed->next)
|
||||
{
|
||||
if ( eed->f & SELECT ) {
|
||||
if (e1 == NULL) {
|
||||
e1 = eed;
|
||||
}
|
||||
else {
|
||||
e2 = eed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (e1->v1 == e2->v1) {
|
||||
v1 = e1->v2;
|
||||
v2 = e1->v1;
|
||||
v3 = e2->v2;
|
||||
}
|
||||
else if (e1->v1 == e2->v2) {
|
||||
v1 = e1->v2;
|
||||
v2 = e1->v1;
|
||||
v3 = e2->v1;
|
||||
}
|
||||
else if (e1->v2 == e2->v1) {
|
||||
v1 = e1->v1;
|
||||
v2 = e1->v2;
|
||||
v3 = e2->v2;
|
||||
}
|
||||
else if (e1->v2 == e2->v2) {
|
||||
v1 = e1->v1;
|
||||
v2 = e1->v2;
|
||||
v3 = e2->v1;
|
||||
}
|
||||
|
||||
if (v1 == NULL)
|
||||
return -1;
|
||||
|
||||
if (confirm == 0 && confirmSpace(set, "Face") == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
VecSubf(tangent, v2->co, v1->co);
|
||||
VecSubf(cotangent, v3->co, v2->co);
|
||||
Crossf(normal, cotangent, tangent);
|
||||
|
||||
Mat4Mul3Vecfl(G.obedit->obmat, normal);
|
||||
Mat4Mul3Vecfl(G.obedit->obmat, tangent);
|
||||
|
||||
if (createSpaceNormal(mat, normal) == 0) {
|
||||
error("Cannot use zero-area face");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(name, "Face");
|
||||
}
|
||||
|
||||
}
|
||||
/* Face Selected */
|
||||
else if(G.scene->selectmode & SCE_SELECT_FACE && G.totfacesel == 1) {
|
||||
/* EditSelection *ese; */
|
||||
EditFace *efa = NULL;
|
||||
float normal[3], tangent[3];
|
||||
|
||||
/*
|
||||
for (ese = em->selected.first; ese; ese = ese->next)
|
||||
{
|
||||
if ( ese->type == EDITFACE ) {
|
||||
efa = (EditFace *)ese->data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
for (efa = em->faces.first; efa; efa = efa->next)
|
||||
{
|
||||
if (efa->f & SELECT)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (efa == NULL)
|
||||
return -1;
|
||||
|
||||
if (confirm == 0 && confirmSpace(set, "Face") == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
VECCOPY(normal, efa->n);
|
||||
VecSubf(tangent, efa->v2->co, efa->v1->co);
|
||||
|
||||
Mat4Mul3Vecfl(G.obedit->obmat, normal);
|
||||
Mat4Mul3Vecfl(G.obedit->obmat, tangent);
|
||||
|
||||
if (createSpaceNormalTangent(mat, normal, tangent) == 0) {
|
||||
error("Cannot use zero-area face");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(name, "Face");
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Input name */
|
||||
sbutton(name, 1, 35, "name: ");
|
||||
|
||||
index = addMatrixSpace(mat, name);
|
||||
return index;
|
||||
}
|
||||
|
||||
int createSpaceNormal(float mat[3][3], float normal[3])
|
||||
{
|
||||
float tangent[3] = {0.0f, 0.0f, 1.0f};
|
||||
|
||||
VECCOPY(mat[2], normal);
|
||||
if (Normalize(mat[2]) == 0.0f) {
|
||||
return 0; /* error return */
|
||||
}
|
||||
|
||||
Crossf(mat[0], mat[2], tangent);
|
||||
if (Inpf(mat[0], mat[0]) == 0.0f) {
|
||||
tangent[0] = 1.0f;
|
||||
tangent[1] = tangent[2] = 0.0f;
|
||||
Crossf(mat[0], tangent, mat[2]);
|
||||
}
|
||||
|
||||
Crossf(mat[1], mat[2], mat[0]);
|
||||
|
||||
Mat3Ortho(mat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3])
|
||||
{
|
||||
VECCOPY(mat[2], normal);
|
||||
if (Normalize(mat[2]) == 0.0f) {
|
||||
return 0; /* error return */
|
||||
}
|
||||
|
||||
Crossf(mat[0], mat[2], tangent);
|
||||
if (Normalize(mat[0]) == 0.0f) {
|
||||
return 0; /* error return */
|
||||
}
|
||||
|
||||
Crossf(mat[1], mat[2], mat[0]);
|
||||
|
||||
Mat3Ortho(mat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int addObjectSpace(Object *ob) {
|
||||
float mat[3][3];
|
||||
char name[36] = "";
|
||||
|
||||
Mat3CpyMat4(mat, ob->obmat);
|
||||
Mat3Ortho(mat);
|
||||
|
||||
strncpy(name, ob->id.name+2, 35);
|
||||
|
||||
/* Input name */
|
||||
sbutton(name, 1, 35, "name: ");
|
||||
|
||||
return addMatrixSpace(mat, name);
|
||||
}
|
||||
|
||||
int addMatrixSpace(float mat[3][3], char name[]) {
|
||||
ListBase *transform_spaces = &G.scene->transform_spaces;
|
||||
TransformOrientation *ts;
|
||||
int index = 0;
|
||||
|
||||
/* if name is found in list, reuse that transform space */
|
||||
for (index = 0, ts = transform_spaces->first; ts; ts = ts->next, index++) {
|
||||
if (strncmp(ts->name, name, 35) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if not, create a new one */
|
||||
if (ts == NULL)
|
||||
{
|
||||
ts = MEM_callocN(sizeof(TransformOrientation), "UserTransSpace from matrix");
|
||||
BLI_addtail(transform_spaces, ts);
|
||||
strncpy(ts->name, name, 35);
|
||||
}
|
||||
|
||||
/* copy matrix into transform space */
|
||||
Mat3CpyMat3(ts->mat, mat);
|
||||
|
||||
BIF_undo_push("Add/Update Transform Orientation");
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void BIF_removeTransformOrientation(TransformOrientation *target) {
|
||||
ListBase *transform_spaces = &G.scene->transform_spaces;
|
||||
TransformOrientation *ts = transform_spaces->first;
|
||||
int selected_index = (G.vd->twmode - V3D_MANIP_CUSTOM);
|
||||
int i;
|
||||
|
||||
for (i = 0, ts = transform_spaces->first; ts; ts = ts->next, i++) {
|
||||
if (ts == target) {
|
||||
if (selected_index == i) {
|
||||
G.vd->twmode = V3D_MANIP_GLOBAL; /* fallback to global */
|
||||
}
|
||||
else if (selected_index > i)
|
||||
G.vd->twmode--;
|
||||
|
||||
BLI_freelinkN(transform_spaces, ts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
BIF_undo_push("Remove Transform Orientation");
|
||||
}
|
||||
|
||||
void BIF_selectTransformOrientation(TransformOrientation *target) {
|
||||
ListBase *transform_spaces = &G.scene->transform_spaces;
|
||||
TransformOrientation *ts = transform_spaces->first;
|
||||
int i;
|
||||
|
||||
for (i = 0, ts = transform_spaces->first; ts; ts = ts->next, i++) {
|
||||
if (ts == target) {
|
||||
G.vd->twmode = V3D_MANIP_CUSTOM + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BIF_selectTransformOrientationFromIndex(int index) {
|
||||
G.vd->twmode = V3D_MANIP_CUSTOM + index;
|
||||
}
|
||||
|
||||
char * BIF_menustringTransformOrientation() {
|
||||
char menu[] = "Orientation%t|Global%x0|Local%x1|Normal%x2|View%x3";
|
||||
ListBase *transform_spaces = &G.scene->transform_spaces;
|
||||
TransformOrientation *ts;
|
||||
int i = V3D_MANIP_CUSTOM;
|
||||
char *str_menu, *p;
|
||||
|
||||
|
||||
str_menu = MEM_callocN(strlen(menu) + 40 * BIF_countTransformOrientation(), "UserTransSpace from matrix");
|
||||
p = str_menu;
|
||||
|
||||
p += sprintf(str_menu, "%s", menu);
|
||||
|
||||
for (ts = transform_spaces->first; ts; ts = ts->next) {
|
||||
p += sprintf(p, "|%s%%x%d", ts->name, i++);
|
||||
}
|
||||
|
||||
return str_menu;
|
||||
}
|
||||
|
||||
int BIF_countTransformOrientation() {
|
||||
ListBase *transform_spaces = &G.scene->transform_spaces;
|
||||
TransformOrientation *ts;
|
||||
int count = 0;
|
||||
|
||||
for (ts = transform_spaces->first; ts; ts = ts->next) {
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void applyTransformOrientation() {
|
||||
TransInfo *t = BIF_GetTransInfo();
|
||||
TransformOrientation *ts;
|
||||
int selected_index = (G.vd->twmode - V3D_MANIP_CUSTOM);
|
||||
int i;
|
||||
|
||||
if (selected_index >= 0) {
|
||||
for (i = 0, ts = G.scene->transform_spaces.first; ts; ts = ts->next, i++) {
|
||||
if (selected_index == i) {
|
||||
strcpy(t->spacename, ts->name);
|
||||
Mat3CpyMat3(t->spacemtx, ts->mat);
|
||||
Mat4CpyMat3(G.vd->twmat, ts->mat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ************************** INPUT FROM MOUSE *************************** */
|
||||
|
||||
|
||||
@@ -234,53 +234,20 @@ int calc_manipulator_stats(ScrArea *sa)
|
||||
EditMesh *em = G.editMesh;
|
||||
EditVert *eve;
|
||||
float vec[3]= {0,0,0};
|
||||
int no_faces= 1;
|
||||
|
||||
/* USE LAST SELECTE WITH ACTIVE */
|
||||
if (G.vd->around==V3D_ACTIVE && em->selected.last) {
|
||||
EM_editselection_center(vec, em->selected.last);
|
||||
calc_tw_center(vec);
|
||||
totsel= 1;
|
||||
if (v3d->twmode == V3D_MANIP_NORMAL) {
|
||||
EM_editselection_normal(normal, em->selected.last);
|
||||
EM_editselection_plane(plane, em->selected.last);
|
||||
} /* NORMAL OPERATION */
|
||||
} else {
|
||||
if(v3d->twmode == V3D_MANIP_NORMAL) {
|
||||
EditFace *efa;
|
||||
|
||||
for(efa= em->faces.first; efa; efa= efa->next) {
|
||||
if(efa->f & SELECT) {
|
||||
no_faces= 0;
|
||||
VECADD(normal, normal, efa->n);
|
||||
VecSubf(vec, efa->v2->co, efa->v1->co);
|
||||
VECADD(plane, plane, vec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* do vertices for center, and if still no normal found, use vertex normals */
|
||||
for(eve= em->verts.first; eve; eve= eve->next) {
|
||||
if(eve->f & SELECT) {
|
||||
if(no_faces) VECADD(normal, normal, eve->no);
|
||||
|
||||
totsel++;
|
||||
calc_tw_center(eve->co);
|
||||
}
|
||||
}
|
||||
/* the edge case... */
|
||||
if(no_faces && v3d->twmode == V3D_MANIP_NORMAL) {
|
||||
EditEdge *eed;
|
||||
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if(eed->f & SELECT) {
|
||||
/* ok we got an edge, only use one, and as normal */
|
||||
VECCOPY(plane, normal);
|
||||
VecSubf(normal, eed->v2->co, eed->v1->co);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* end editmesh */
|
||||
else if (G.obedit->type==OB_ARMATURE){
|
||||
@@ -314,22 +281,18 @@ int calc_manipulator_stats(ScrArea *sa)
|
||||
if( (bezt->f1 & SELECT) + (bezt->f2 & SELECT) + (bezt->f3 & SELECT) > SELECT ) {
|
||||
calc_tw_center(bezt->vec[1]);
|
||||
totsel++;
|
||||
VecSubf(normal, bezt->vec[0], bezt->vec[2]);
|
||||
}
|
||||
else {
|
||||
if(bezt->f1) {
|
||||
calc_tw_center(bezt->vec[0]);
|
||||
VecSubf(normal, bezt->vec[0], bezt->vec[1]);
|
||||
totsel++;
|
||||
}
|
||||
if(bezt->f2) {
|
||||
calc_tw_center(bezt->vec[1]);
|
||||
VecSubf(normal, bezt->vec[0], bezt->vec[2]);
|
||||
totsel++;
|
||||
}
|
||||
if(bezt->f3) {
|
||||
calc_tw_center(bezt->vec[2]);
|
||||
VecSubf(normal, bezt->vec[1], bezt->vec[2]);
|
||||
totsel++;
|
||||
}
|
||||
}
|
||||
@@ -364,23 +327,6 @@ int calc_manipulator_stats(ScrArea *sa)
|
||||
}
|
||||
ml= ml->next;
|
||||
}
|
||||
/* normal manipulator */
|
||||
if(totsel==1){
|
||||
float mat1[4][4];
|
||||
|
||||
/* Rotation of MetaElem is stored in quat */
|
||||
QuatToMat4(ml_sel->quat, mat1);
|
||||
|
||||
/* Translation of MetaElem */
|
||||
mat1[3][0]= ml_sel->x;
|
||||
mat1[3][1]= ml_sel->y;
|
||||
mat1[3][2]= ml_sel->z;
|
||||
|
||||
VECCOPY(normal, mat1[2]);
|
||||
VECCOPY(plane, mat1[1]);
|
||||
|
||||
VecMulf(plane, -1.0);
|
||||
}
|
||||
}
|
||||
else if(G.obedit->type==OB_LATTICE) {
|
||||
BPoint *bp;
|
||||
@@ -490,6 +436,54 @@ int calc_manipulator_stats(ScrArea *sa)
|
||||
|
||||
case V3D_MANIP_NORMAL:
|
||||
if(G.obedit || (ob->flag & OB_POSEMODE)) {
|
||||
float mat[3][3];
|
||||
int type;
|
||||
|
||||
strcpy(t->spacename, "normal");
|
||||
|
||||
type = getTransformOrientation(normal, plane, 0);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ORIENTATION_NORMAL:
|
||||
if (createSpaceNormalTangent(mat, normal, plane) == 0)
|
||||
{
|
||||
type = ORIENTATION_NONE;
|
||||
}
|
||||
break;
|
||||
case ORIENTATION_VERT:
|
||||
if (createSpaceNormal(mat, normal) == 0)
|
||||
{
|
||||
type = ORIENTATION_NONE;
|
||||
}
|
||||
break;
|
||||
case ORIENTATION_EDGE:
|
||||
if (createSpaceNormalTangent(mat, normal, plane) == 0)
|
||||
{
|
||||
type = ORIENTATION_NONE;
|
||||
}
|
||||
break;
|
||||
case ORIENTATION_FACE:
|
||||
if (createSpaceNormalTangent(mat, normal, plane) == 0)
|
||||
{
|
||||
type = ORIENTATION_NONE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == ORIENTATION_NONE)
|
||||
{
|
||||
Mat4One(v3d->twmat);
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat4CpyMat3(v3d->twmat, mat);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* pose mode is a bit weird, so keep it separated */
|
||||
else if (ob->flag & OB_POSEMODE)
|
||||
{
|
||||
strcpy(t->spacename, "normal");
|
||||
if(normal[0]!=0.0 || normal[1]!=0.0 || normal[2]!=0.0) {
|
||||
float imat[3][3], mat[3][3];
|
||||
|
||||
616
source/blender/src/transform_orientations.c
Normal file
616
source/blender/src/transform_orientations.c
Normal file
@@ -0,0 +1,616 @@
|
||||
/**
|
||||
* $Id:
|
||||
*
|
||||
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version. The Blender
|
||||
* Foundation also sells licenses for use in proprietary software under
|
||||
* the Blender License. See http://www.blender.org/BL/ for information
|
||||
* about this.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Contributor(s): Martin Poirier
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meta_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_editVert.h"
|
||||
|
||||
#include "BIF_editmesh.h"
|
||||
#include "BIF_interface.h"
|
||||
#include "BIF_space.h"
|
||||
#include "BIF_toolbox.h"
|
||||
|
||||
#include "blendef.h"
|
||||
|
||||
|
||||
#include "transform.h"
|
||||
|
||||
|
||||
/* *********************** TransSpace ************************** */
|
||||
|
||||
void BIF_clearTransformOrientation(void)
|
||||
{
|
||||
ListBase *transform_spaces = &G.scene->transform_spaces;
|
||||
BLI_freelistN(transform_spaces);
|
||||
|
||||
if (G.vd->twmode >= V3D_MANIP_CUSTOM)
|
||||
G.vd->twmode = V3D_MANIP_GLOBAL; /* fallback to global */
|
||||
}
|
||||
|
||||
void BIF_manageTransformOrientation(int confirm, int set) {
|
||||
int index = -1;
|
||||
|
||||
if (G.obedit) {
|
||||
if (G.obedit->type == OB_MESH)
|
||||
index = manageMeshSpace(confirm, set);
|
||||
}
|
||||
else {
|
||||
index = manageObjectSpace(confirm, set);
|
||||
}
|
||||
|
||||
if (set && index != -1)
|
||||
{
|
||||
BIF_selectTransformOrientationFromIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
int manageObjectSpace(int confirm, int set) {
|
||||
Base *base = BASACT;
|
||||
|
||||
if (base == NULL)
|
||||
return -1;
|
||||
|
||||
if (confirm == 0) {
|
||||
if (set && pupmenu("Custom Orientation %t|Add and Use Active Object%x1") != 1) {
|
||||
return -1;
|
||||
}
|
||||
else if (set == 0 && pupmenu("Custom Orientation %t|Add Active Object%x1") != 1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return addObjectSpace(base->object);
|
||||
}
|
||||
|
||||
/* return 1 on confirm */
|
||||
int confirmSpace(int set, char text[])
|
||||
{
|
||||
char menu[64];
|
||||
|
||||
if (set) {
|
||||
sprintf(menu, "Custom Orientation %%t|Add and Use %s%%x1", text);
|
||||
}
|
||||
else {
|
||||
sprintf(menu, "Custom Orientation %%t|Add %s%%x1", text);
|
||||
}
|
||||
|
||||
if (pupmenu(menu) == 1) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int manageMeshSpace(int confirm, int set) {
|
||||
float mat[3][3];
|
||||
float normal[3], plane[3];
|
||||
char name[36] = "";
|
||||
int index;
|
||||
int type;
|
||||
|
||||
type = getTransformOrientation(normal, plane, 0);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ORIENTATION_VERT:
|
||||
if (confirm == 0 && confirmSpace(set, "vertex") == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (createSpaceNormal(mat, normal) == 0) {
|
||||
error("Cannot use vertex with zero-length normal");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(name, "Vertex");
|
||||
break;
|
||||
case ORIENTATION_EDGE:
|
||||
if (confirm == 0 && confirmSpace(set, "Edge") == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (createSpaceNormalTangent(mat, normal, plane) == 0) {
|
||||
error("Cannot use zero-length edge");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(name, "Edge");
|
||||
break;
|
||||
case ORIENTATION_FACE:
|
||||
if (confirm == 0 && confirmSpace(set, "Face") == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (createSpaceNormalTangent(mat, normal, plane) == 0) {
|
||||
error("Cannot use zero-area face");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(name, "Face");
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Input name */
|
||||
sbutton(name, 1, 35, "name: ");
|
||||
|
||||
index = addMatrixSpace(mat, name);
|
||||
return index;
|
||||
}
|
||||
|
||||
int createSpaceNormal(float mat[3][3], float normal[3])
|
||||
{
|
||||
float tangent[3] = {0.0f, 0.0f, 1.0f};
|
||||
|
||||
VECCOPY(mat[2], normal);
|
||||
if (Normalize(mat[2]) == 0.0f) {
|
||||
return 0; /* error return */
|
||||
}
|
||||
|
||||
Crossf(mat[0], mat[2], tangent);
|
||||
if (Inpf(mat[0], mat[0]) == 0.0f) {
|
||||
tangent[0] = 1.0f;
|
||||
tangent[1] = tangent[2] = 0.0f;
|
||||
Crossf(mat[0], tangent, mat[2]);
|
||||
}
|
||||
|
||||
Crossf(mat[1], mat[2], mat[0]);
|
||||
|
||||
Mat3Ortho(mat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3])
|
||||
{
|
||||
VECCOPY(mat[2], normal);
|
||||
if (Normalize(mat[2]) == 0.0f) {
|
||||
return 0; /* error return */
|
||||
}
|
||||
|
||||
/* preempt zero length tangent from causing trouble */
|
||||
if (tangent[0] == 0 && tangent[1] == 0 && tangent[2] == 0)
|
||||
{
|
||||
tangent[2] = 1;
|
||||
}
|
||||
|
||||
Crossf(mat[0], mat[2], tangent);
|
||||
if (Normalize(mat[0]) == 0.0f) {
|
||||
return 0; /* error return */
|
||||
}
|
||||
|
||||
Crossf(mat[1], mat[2], mat[0]);
|
||||
|
||||
Mat3Ortho(mat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int addObjectSpace(Object *ob) {
|
||||
float mat[3][3];
|
||||
char name[36] = "";
|
||||
|
||||
Mat3CpyMat4(mat, ob->obmat);
|
||||
Mat3Ortho(mat);
|
||||
|
||||
strncpy(name, ob->id.name+2, 35);
|
||||
|
||||
/* Input name */
|
||||
sbutton(name, 1, 35, "name: ");
|
||||
|
||||
return addMatrixSpace(mat, name);
|
||||
}
|
||||
|
||||
int addMatrixSpace(float mat[3][3], char name[]) {
|
||||
ListBase *transform_spaces = &G.scene->transform_spaces;
|
||||
TransformOrientation *ts;
|
||||
int index = 0;
|
||||
|
||||
/* if name is found in list, reuse that transform space */
|
||||
for (index = 0, ts = transform_spaces->first; ts; ts = ts->next, index++) {
|
||||
if (strncmp(ts->name, name, 35) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if not, create a new one */
|
||||
if (ts == NULL)
|
||||
{
|
||||
ts = MEM_callocN(sizeof(TransformOrientation), "UserTransSpace from matrix");
|
||||
BLI_addtail(transform_spaces, ts);
|
||||
strncpy(ts->name, name, 35);
|
||||
}
|
||||
|
||||
/* copy matrix into transform space */
|
||||
Mat3CpyMat3(ts->mat, mat);
|
||||
|
||||
BIF_undo_push("Add/Update Transform Orientation");
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void BIF_removeTransformOrientation(TransformOrientation *target) {
|
||||
ListBase *transform_spaces = &G.scene->transform_spaces;
|
||||
TransformOrientation *ts = transform_spaces->first;
|
||||
int selected_index = (G.vd->twmode - V3D_MANIP_CUSTOM);
|
||||
int i;
|
||||
|
||||
for (i = 0, ts = transform_spaces->first; ts; ts = ts->next, i++) {
|
||||
if (ts == target) {
|
||||
if (selected_index == i) {
|
||||
G.vd->twmode = V3D_MANIP_GLOBAL; /* fallback to global */
|
||||
}
|
||||
else if (selected_index > i)
|
||||
G.vd->twmode--;
|
||||
|
||||
BLI_freelinkN(transform_spaces, ts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
BIF_undo_push("Remove Transform Orientation");
|
||||
}
|
||||
|
||||
void BIF_selectTransformOrientation(TransformOrientation *target) {
|
||||
ListBase *transform_spaces = &G.scene->transform_spaces;
|
||||
TransformOrientation *ts = transform_spaces->first;
|
||||
int i;
|
||||
|
||||
for (i = 0, ts = transform_spaces->first; ts; ts = ts->next, i++) {
|
||||
if (ts == target) {
|
||||
G.vd->twmode = V3D_MANIP_CUSTOM + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BIF_selectTransformOrientationFromIndex(int index) {
|
||||
G.vd->twmode = V3D_MANIP_CUSTOM + index;
|
||||
}
|
||||
|
||||
char * BIF_menustringTransformOrientation() {
|
||||
char menu[] = "Orientation%t|Global%x0|Local%x1|Normal%x2|View%x3";
|
||||
ListBase *transform_spaces = &G.scene->transform_spaces;
|
||||
TransformOrientation *ts;
|
||||
int i = V3D_MANIP_CUSTOM;
|
||||
char *str_menu, *p;
|
||||
|
||||
|
||||
str_menu = MEM_callocN(strlen(menu) + 40 * BIF_countTransformOrientation(), "UserTransSpace from matrix");
|
||||
p = str_menu;
|
||||
|
||||
p += sprintf(str_menu, "%s", menu);
|
||||
|
||||
for (ts = transform_spaces->first; ts; ts = ts->next) {
|
||||
p += sprintf(p, "|%s%%x%d", ts->name, i++);
|
||||
}
|
||||
|
||||
return str_menu;
|
||||
}
|
||||
|
||||
int BIF_countTransformOrientation() {
|
||||
ListBase *transform_spaces = &G.scene->transform_spaces;
|
||||
TransformOrientation *ts;
|
||||
int count = 0;
|
||||
|
||||
for (ts = transform_spaces->first; ts; ts = ts->next) {
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void applyTransformOrientation() {
|
||||
TransInfo *t = BIF_GetTransInfo();
|
||||
TransformOrientation *ts;
|
||||
int selected_index = (G.vd->twmode - V3D_MANIP_CUSTOM);
|
||||
int i;
|
||||
|
||||
if (selected_index >= 0) {
|
||||
for (i = 0, ts = G.scene->transform_spaces.first; ts; ts = ts->next, i++) {
|
||||
if (selected_index == i) {
|
||||
strcpy(t->spacename, ts->name);
|
||||
Mat3CpyMat3(t->spacemtx, ts->mat);
|
||||
Mat4CpyMat3(G.vd->twmat, ts->mat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int getTransformOrientation(float normal[3], float plane[3], int activeOnly)
|
||||
{
|
||||
Base *base;
|
||||
Object *ob = OBACT;
|
||||
int result = ORIENTATION_NONE;
|
||||
|
||||
normal[0] = normal[1] = normal[2] = 0;
|
||||
plane[0] = plane[1] = plane[2] = 0;
|
||||
|
||||
if(G.obedit)
|
||||
{
|
||||
ob= G.obedit;
|
||||
|
||||
if(G.obedit->type==OB_MESH)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
EditVert *eve;
|
||||
float vec[3]= {0,0,0};
|
||||
|
||||
/* USE LAST SELECTED WITH ACTIVE */
|
||||
if (activeOnly && em->selected.last)
|
||||
{
|
||||
EditSelection *ese = em->selected.last;
|
||||
EM_editselection_normal(normal, ese);
|
||||
EM_editselection_plane(plane, ese);
|
||||
|
||||
switch (ese->type)
|
||||
{
|
||||
case EDITVERT:
|
||||
result = ORIENTATION_VERT;
|
||||
break;
|
||||
case EDITEDGE:
|
||||
result = ORIENTATION_EDGE;
|
||||
break;
|
||||
case EDITFACE:
|
||||
result = ORIENTATION_FACE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (G.totfacesel >= 1)
|
||||
{
|
||||
EditFace *efa;
|
||||
|
||||
for(efa= em->faces.first; efa; efa= efa->next)
|
||||
{
|
||||
if(efa->f & SELECT)
|
||||
{
|
||||
VECADD(normal, normal, efa->n);
|
||||
VecSubf(vec, efa->v2->co, efa->v1->co);
|
||||
VECADD(plane, plane, vec);
|
||||
}
|
||||
}
|
||||
|
||||
result = ORIENTATION_FACE;
|
||||
}
|
||||
else if (G.totvertsel == 3)
|
||||
{
|
||||
EditVert *v1 = NULL, *v2 = NULL, *v3 = NULL;
|
||||
float cotangent[3];
|
||||
|
||||
for (eve = em->verts.first; eve; eve = eve->next)
|
||||
{
|
||||
if ( eve->f & SELECT ) {
|
||||
if (v1 == NULL) {
|
||||
v1 = eve;
|
||||
}
|
||||
else if (v2 == NULL) {
|
||||
v2 = eve;
|
||||
}
|
||||
else {
|
||||
v3 = eve;
|
||||
|
||||
VecSubf(plane, v2->co, v1->co);
|
||||
VecSubf(cotangent, v3->co, v2->co);
|
||||
Crossf(normal, cotangent, plane);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
result = ORIENTATION_FACE;
|
||||
}
|
||||
else if (G.totedgesel == 1)
|
||||
{
|
||||
EditEdge *eed;
|
||||
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if(eed->f & SELECT) {
|
||||
/* use average vert normals as plane and edge vector as normal */
|
||||
VECCOPY(plane, eed->v1->no);
|
||||
VECADD(plane, plane, eed->v2->no);
|
||||
VecSubf(normal, eed->v2->co, eed->v1->co);
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = ORIENTATION_EDGE;
|
||||
}
|
||||
else if (G.totvertsel == 2)
|
||||
{
|
||||
EditVert *v1 = NULL, *v2 = NULL;
|
||||
|
||||
for (eve = em->verts.first; eve; eve = eve->next)
|
||||
{
|
||||
if ( eve->f & SELECT ) {
|
||||
if (v1 == NULL) {
|
||||
v1 = eve;
|
||||
}
|
||||
else {
|
||||
v2 = eve;
|
||||
|
||||
VECCOPY(plane, v1->no);
|
||||
VECADD(plane, plane, v2->no);
|
||||
VecSubf(normal, v2->co, v1->co);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
result = ORIENTATION_EDGE;
|
||||
}
|
||||
else if (G.totvertsel == 1)
|
||||
{
|
||||
for (eve = em->verts.first; eve; eve = eve->next)
|
||||
{
|
||||
if ( eve->f & SELECT ) {
|
||||
VECCOPY(normal, eve->no);
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = ORIENTATION_VERT;
|
||||
}
|
||||
}
|
||||
} /* end editmesh */
|
||||
else if ELEM3(G.obedit->type, OB_CURVE, OB_SURF, OB_FONT)
|
||||
{
|
||||
extern ListBase editNurb; /* BOOO! go away stupid extern */
|
||||
Nurb *nu;
|
||||
BezTriple *bezt;
|
||||
int a;
|
||||
|
||||
for (nu = editNurb.first; nu; nu = nu->next)
|
||||
{
|
||||
/* only bezier has a normal */
|
||||
if((nu->type & 7) == CU_BEZIER)
|
||||
{
|
||||
bezt= nu->bezt;
|
||||
a= nu->pntsu;
|
||||
while(a--)
|
||||
{
|
||||
/* exception */
|
||||
if ( (bezt->f1 & SELECT) + (bezt->f2 & SELECT) + (bezt->f3 & SELECT) > SELECT )
|
||||
{
|
||||
VecSubf(normal, bezt->vec[0], bezt->vec[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(bezt->f1)
|
||||
{
|
||||
VecSubf(normal, bezt->vec[0], bezt->vec[1]);
|
||||
}
|
||||
if(bezt->f2)
|
||||
{
|
||||
VecSubf(normal, bezt->vec[0], bezt->vec[2]);
|
||||
}
|
||||
if(bezt->f3)
|
||||
{
|
||||
VecSubf(normal, bezt->vec[1], bezt->vec[2]);
|
||||
}
|
||||
}
|
||||
bezt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (normal[0] != 0 || normal[1] != 0 || normal[2] != 0)
|
||||
{
|
||||
result = ORIENTATION_NORMAL;
|
||||
}
|
||||
}
|
||||
else if(G.obedit->type==OB_MBALL)
|
||||
{
|
||||
/* editmball.c */
|
||||
extern ListBase editelems; /* go away ! */
|
||||
MetaElem *ml, *ml_sel = NULL;
|
||||
|
||||
/* loop and check that only one element is selected */
|
||||
for (ml = editelems.first; ml; ml = ml->next)
|
||||
{
|
||||
if (ml->flag & SELECT) {
|
||||
if (ml_sel == NULL)
|
||||
{
|
||||
ml_sel = ml;
|
||||
}
|
||||
else
|
||||
{
|
||||
ml_sel = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ml_sel)
|
||||
{
|
||||
float mat[4][4];
|
||||
|
||||
/* Rotation of MetaElem is stored in quat */
|
||||
QuatToMat4(ml_sel->quat, mat);
|
||||
|
||||
VECCOPY(normal, mat[2]);
|
||||
VECCOPY(plane, mat[1]);
|
||||
|
||||
VecMulf(plane, -1.0);
|
||||
|
||||
result = ORIENTATION_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
Mat4Mul3Vecfl(G.obedit->obmat, plane);
|
||||
Mat4Mul3Vecfl(G.obedit->obmat, normal);
|
||||
}
|
||||
else if(ob && (ob->flag & OB_POSEMODE))
|
||||
{
|
||||
}
|
||||
else if(G.f & (G_VERTEXPAINT + G_TEXTUREPAINT + G_WEIGHTPAINT + G_SCULPTMODE))
|
||||
{
|
||||
}
|
||||
else if(G.f & G_PARTICLEEDIT)
|
||||
{
|
||||
}
|
||||
else {
|
||||
/* we need the one selected object, if its not active */
|
||||
ob = OBACT;
|
||||
if(ob && !(ob->flag & SELECT)) ob = NULL;
|
||||
|
||||
for(base= G.scene->base.first; base; base= base->next) {
|
||||
if TESTBASELIB(base) {
|
||||
if(ob == NULL) {
|
||||
ob= base->object;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VECCOPY(normal, ob->obmat[2]);
|
||||
VECCOPY(plane, ob->obmat[1]);
|
||||
result = ORIENTATION_NORMAL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user