commit of patch 19268, rotate uvs by wael oraiby
This commit is contained in:
@@ -97,6 +97,10 @@ static void mesh_ensure_tesselation_customdata(Mesh *me)
|
||||
totcol != CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL))
|
||||
{
|
||||
CustomData_free(&me->fdata, me->totface);
|
||||
|
||||
me->mface = (void*)me->mtface = (void*)me->mcol = NULL;
|
||||
me->totface = 0;
|
||||
|
||||
memset(&me->fdata, 0, sizeof(&me->fdata));
|
||||
|
||||
CustomData_from_bmeshpoly(&me->fdata, &me->pdata, &me->ldata, me->totface);
|
||||
|
||||
@@ -50,6 +50,16 @@ enum {
|
||||
SIMVERT_VGROUP,
|
||||
};
|
||||
|
||||
enum {
|
||||
OPUVC_AXIS_X = 1,
|
||||
OPUVC_AXIS_Y
|
||||
};
|
||||
|
||||
enum {
|
||||
DIRECTION_CW = 1,
|
||||
DIRECTION_CCW
|
||||
};
|
||||
|
||||
extern BMOpDefine *opdefines[];
|
||||
extern int bmesh_total_ops;
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@ void BM_add_data_layer(BMesh *bm, CustomData *data, int type)
|
||||
|
||||
olddata= *data;
|
||||
olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
|
||||
CustomData_add_layer(data, type, CD_CALLOC, NULL, 0);
|
||||
CustomData_add_layer(data, type, CD_DEFAULT, NULL, 0);
|
||||
|
||||
update_data_blocks(bm, &olddata, data);
|
||||
if (olddata.layers) MEM_freeN(olddata.layers);
|
||||
|
||||
@@ -690,6 +690,19 @@ BMOpDefine def_similarverts = {
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
** uv rotation
|
||||
** cycle the uvs
|
||||
*/
|
||||
BMOpDefine def_meshrotateuvs = {
|
||||
"meshrotateuvs",
|
||||
{{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, /* input faces */
|
||||
{BMOP_OPSLOT_INT, "dir"}, /* direction */
|
||||
{0} /*null-terminating sentinel*/},
|
||||
bmesh_rotateuvs_exec,
|
||||
0
|
||||
};
|
||||
|
||||
BMOpDefine *opdefines[] = {
|
||||
&def_splitop,
|
||||
&def_dupeop,
|
||||
@@ -735,6 +748,7 @@ BMOpDefine *opdefines[] = {
|
||||
&def_similarverts,
|
||||
&def_pointmerge_facedata,
|
||||
&def_vert_average_facedata,
|
||||
&def_meshrotateuvs,
|
||||
};
|
||||
|
||||
int bmesh_total_ops = (sizeof(opdefines) / sizeof(void*));
|
||||
|
||||
@@ -51,5 +51,6 @@ void bmesh_similaredges_exec(BMesh *bm, BMOperator *op);
|
||||
void bmesh_similarverts_exec(BMesh *bm, BMOperator *op);
|
||||
void bmesh_pointmerge_facedata_exec(BMesh *bm, BMOperator *op);
|
||||
void bmesh_vert_average_facedata_exec(BMesh *bm, BMOperator *op);
|
||||
void bmesh_rotateuvs_exec(BMesh *bm, BMOperator *op);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -891,11 +891,11 @@ void bmesh_similarverts_exec(BMesh *bm, BMOperator *op)
|
||||
switch( type ) {
|
||||
case SIMVERT_FACE:
|
||||
/* calling BM_Vert_FaceCount every time is time consumming, so call it only once per vertex */
|
||||
v_ext[i].num_faces = BM_Vert_FaceCount(v);
|
||||
v_ext[i].num_faces = BM_Vert_FaceCount(v);
|
||||
break;
|
||||
|
||||
case SIMVERT_VGROUP:
|
||||
if( CustomData_has_layer(&(bm->vdata), CD_MDEFORMVERT) ) {
|
||||
if( CustomData_has_layer(&(bm->vdata),CD_MDEFORMVERT) ) {
|
||||
v_ext[i].dvert = CustomData_bmesh_get(&bm->vdata, v_ext[i].v->head.data, CD_MDEFORMVERT);
|
||||
} else v_ext[i].dvert = NULL;
|
||||
break;
|
||||
@@ -952,3 +952,75 @@ void bmesh_similarverts_exec(BMesh *bm, BMOperator *op)
|
||||
|
||||
BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
** Cycle UVs for a face
|
||||
******************************************************************************/
|
||||
|
||||
void bmesh_rotateuvs_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
BMOIter fs_iter; /* selected faces iterator */
|
||||
BMFace *fs; /* current face */
|
||||
BMIter l_iter; /* iteration loop */
|
||||
int n;
|
||||
|
||||
int dir = BMO_Get_Int(op, "dir");
|
||||
|
||||
BMO_ITER(fs, &fs_iter, bm, op, "faces", BM_FACE) {
|
||||
if( CustomData_has_layer(&(bm->ldata), CD_MLOOPUV) ) {
|
||||
if( dir == DIRECTION_CW ) { /* same loops direction */
|
||||
BMLoop *lf; /* current face loops */
|
||||
MLoopUV *f_luv; /* first face loop uv */
|
||||
float p_uv[2]; /* previous uvs */
|
||||
float t_uv[2]; /* tmp uvs */
|
||||
|
||||
int n = 0;
|
||||
BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
|
||||
/* current loop uv is the previous loop uv */
|
||||
MLoopUV *luv = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPUV);
|
||||
if( n == 0 ) {
|
||||
f_luv = luv;
|
||||
p_uv[0] = luv->uv[0];
|
||||
p_uv[1] = luv->uv[1];
|
||||
} else {
|
||||
t_uv[0] = luv->uv[0];
|
||||
t_uv[1] = luv->uv[1];
|
||||
luv->uv[0] = p_uv[0];
|
||||
luv->uv[1] = p_uv[1];
|
||||
p_uv[0] = t_uv[0];
|
||||
p_uv[1] = t_uv[1];
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
f_luv->uv[0] = p_uv[0];
|
||||
f_luv->uv[1] = p_uv[1];
|
||||
} else if( dir == DIRECTION_CCW ) { /* counter loop direction */
|
||||
BMLoop *lf; /* current face loops */
|
||||
MLoopUV *p_luv; /*previous loop uv */
|
||||
MLoopUV *luv;
|
||||
float t_uv[2]; /* current uvs */
|
||||
|
||||
int n = 0;
|
||||
BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
|
||||
/* previous loop uv is the current loop uv */
|
||||
luv = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPUV);
|
||||
if( n == 0 ) {
|
||||
p_luv = luv;
|
||||
t_uv[0] = luv->uv[0];
|
||||
t_uv[1] = luv->uv[1];
|
||||
} else {
|
||||
p_luv->uv[0] = luv->uv[0];
|
||||
p_luv->uv[1] = luv->uv[1];
|
||||
p_luv = luv;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
luv->uv[0] = t_uv[0];
|
||||
luv->uv[1] = t_uv[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -710,205 +710,6 @@ static EnumPropertyItem prop_simedge_types[] = {
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
static int similar_edge_select__internal(Scene *scene, EditMesh *em, int mode)
|
||||
{
|
||||
#if 0
|
||||
EditEdge *eed, *base_eed=NULL;
|
||||
unsigned int selcount=0; /* count how many new edges we select*/
|
||||
|
||||
/*count how many visible selected edges there are,
|
||||
so we can return when there are none left */
|
||||
unsigned int deselcount=0;
|
||||
|
||||
short ok=0;
|
||||
float thresh= scene->toolsettings->select_thresh;
|
||||
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if (!eed->h) {
|
||||
if (eed->f & SELECT) {
|
||||
eed->f1=1;
|
||||
ok=1;
|
||||
} else {
|
||||
eed->f1=0;
|
||||
deselcount++;
|
||||
}
|
||||
/* set all eed->tmp.l to 0 we use it later.
|
||||
for counting face users*/
|
||||
eed->tmp.l=0;
|
||||
eed->f2=0; /* only for mode SIMEDGE_FACE_ANGLE, edge animations */
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok || !deselcount) /* no data selected OR no more data to select*/
|
||||
return 0;
|
||||
|
||||
if (mode==SIMEDGE_LENGTH) { /*store length*/
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if (!eed->h) /* dont calc data for hidden edges*/
|
||||
eed->tmp.fp= VecLenf(eed->v1->co, eed->v2->co);
|
||||
}
|
||||
} else if (mode==SIMEDGE_FACE) { /*store face users*/
|
||||
EditFace *efa;
|
||||
/* cound how many faces each edge uses use tmp->l */
|
||||
for(efa= em->faces.first; efa; efa= efa->next) {
|
||||
efa->e1->tmp.l++;
|
||||
efa->e2->tmp.l++;
|
||||
efa->e3->tmp.l++;
|
||||
if (efa->e4) efa->e4->tmp.l++;
|
||||
}
|
||||
} else if (mode==SIMEDGE_FACE_ANGLE) { /*store edge angles */
|
||||
EditFace *efa;
|
||||
int j;
|
||||
/* cound how many faces each edge uses use tmp.l */
|
||||
for(efa= em->faces.first; efa; efa= efa->next) {
|
||||
/* here we use the edges temp data to assign a face
|
||||
if a face has alredy been assigned (eed->f2==1)
|
||||
we calculate the angle between the current face and
|
||||
the edges previously found face.
|
||||
store the angle in eed->tmp.fp (loosing the face eed->tmp.f)
|
||||
but tagging eed->f2==2, so we know not to look at it again.
|
||||
This only works for edges that connect to 2 faces. but its good enough
|
||||
*/
|
||||
|
||||
/* se we can loop through face edges*/
|
||||
j=0;
|
||||
eed= efa->e1;
|
||||
while (j<4) {
|
||||
if (j==1) eed= efa->e2;
|
||||
else if (j==2) eed= efa->e3;
|
||||
else if (j==3) {
|
||||
eed= efa->e4;
|
||||
if (!eed)
|
||||
break;
|
||||
} /* done looping */
|
||||
|
||||
if (!eed->h) { /* dont calc data for hidden edges*/
|
||||
if (eed->f2==2)
|
||||
break;
|
||||
else if (eed->f2==0) /* first access, assign the face */
|
||||
eed->tmp.f= efa;
|
||||
else if (eed->f2==1) /* second, we assign the angle*/
|
||||
eed->tmp.fp= VecAngle2(eed->tmp.f->n, efa->n)/180;
|
||||
eed->f2++; /* f2==0 no face assigned. f2==1 one face found. f2==2 angle calculated.*/
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(base_eed= em->edges.first; base_eed; base_eed= base_eed->next) {
|
||||
if (base_eed->f1) {
|
||||
if (mode==SIMEDGE_LENGTH) { /* same length */
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if (
|
||||
!(eed->f & SELECT) &&
|
||||
!eed->h &&
|
||||
SCALE_CMP(base_eed->tmp.fp, eed->tmp.fp)
|
||||
) {
|
||||
EM_select_edge(eed, 1);
|
||||
selcount++;
|
||||
deselcount--;
|
||||
if (!deselcount) /*have we selected all posible faces?, if so return*/
|
||||
return selcount;
|
||||
}
|
||||
}
|
||||
} else if (mode==SIMEDGE_DIR) { /* same direction */
|
||||
float base_dir[3], dir[3], angle;
|
||||
VecSubf(base_dir, base_eed->v1->co, base_eed->v2->co);
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if (!(eed->f & SELECT) && !eed->h) {
|
||||
VecSubf(dir, eed->v1->co, eed->v2->co);
|
||||
angle= VecAngle2(base_dir, dir);
|
||||
|
||||
if (angle>90) /* use the smallest angle between the edges */
|
||||
angle= fabs(angle-180.0f);
|
||||
|
||||
if (angle/90.0<=thresh) {
|
||||
EM_select_edge(eed, 1);
|
||||
selcount++;
|
||||
deselcount--;
|
||||
if (!deselcount) /*have we selected all posible faces?, if so return*/
|
||||
return selcount;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (mode==SIMEDGE_FACE) { /* face users */
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if (
|
||||
!(eed->f & SELECT) &&
|
||||
!eed->h &&
|
||||
base_eed->tmp.l==eed->tmp.l
|
||||
) {
|
||||
EM_select_edge(eed, 1);
|
||||
selcount++;
|
||||
deselcount--;
|
||||
if (!deselcount) /*have we selected all posible faces?, if so return*/
|
||||
return selcount;
|
||||
}
|
||||
}
|
||||
} else if (mode==SIMEDGE_FACE_ANGLE && base_eed->f2==2) { /* edge angles, f2==2 means the edge has an angle. */
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if (
|
||||
!(eed->f & SELECT) &&
|
||||
!eed->h &&
|
||||
eed->f2==2 &&
|
||||
(fabs(base_eed->tmp.fp-eed->tmp.fp)<=thresh)
|
||||
) {
|
||||
EM_select_edge(eed, 1);
|
||||
selcount++;
|
||||
deselcount--;
|
||||
if (!deselcount) /*have we selected all posible faces?, if so return*/
|
||||
return selcount;
|
||||
}
|
||||
}
|
||||
} else if (mode==SIMEDGE_CREASE) { /* edge crease */
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if (
|
||||
!(eed->f & SELECT) &&
|
||||
!eed->h &&
|
||||
(fabs(base_eed->crease-eed->crease) <= thresh)
|
||||
) {
|
||||
EM_select_edge(eed, 1);
|
||||
selcount++;
|
||||
deselcount--;
|
||||
if (!deselcount) /*have we selected all posible faces?, if so return*/
|
||||
return selcount;
|
||||
}
|
||||
}
|
||||
} else if (mode==SIMEDGE_SEAM) { /* edge seam */
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if (
|
||||
!(eed->f & SELECT) &&
|
||||
!eed->h &&
|
||||
(eed->seam == base_eed->seam)
|
||||
) {
|
||||
EM_select_edge(eed, 1);
|
||||
selcount++;
|
||||
deselcount--;
|
||||
if (!deselcount) /*have we selected all posible faces?, if so return*/
|
||||
return selcount;
|
||||
}
|
||||
}
|
||||
} else if (mode==SIMEDGE_SHARP) { /* edge sharp */
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if (
|
||||
!(eed->f & SELECT) &&
|
||||
!eed->h &&
|
||||
(eed->sharp == base_eed->sharp)
|
||||
) {
|
||||
EM_select_edge(eed, 1);
|
||||
selcount++;
|
||||
deselcount--;
|
||||
if (!deselcount) /*have we selected all posible faces?, if so return*/
|
||||
return selcount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return selcount;
|
||||
#endif
|
||||
}
|
||||
/* wrap the above function but do selection flushing edge to face */
|
||||
static int similar_edge_select_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
@@ -945,25 +746,6 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op)
|
||||
|
||||
/* we succeeded */
|
||||
return OPERATOR_FINISHED;
|
||||
#if 0
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
Mesh *me= obedit->data;
|
||||
EditMesh *em= BKE_mesh_get_editmesh(me);
|
||||
|
||||
int selcount = similar_edge_select__internal(scene, em, RNA_int_get(op->ptr, "type"));
|
||||
|
||||
if (selcount) {
|
||||
/* here was an edge-mode only select flush case, has to be generalized */
|
||||
EM_selectmode_flush(em);
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
|
||||
BKE_mesh_end_editmesh(me, em);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
BKE_mesh_end_editmesh(me, em);
|
||||
return OPERATOR_CANCELLED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ********************************* */
|
||||
|
||||
@@ -1617,8 +1617,8 @@ void MESH_OT_flip_normals(wmOperatorType *ot)
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
#define DIRECTION_CW 1
|
||||
#define DIRECTION_CCW 2
|
||||
//#define DIRECTION_CW 1
|
||||
//#define DIRECTION_CCW 2
|
||||
|
||||
static const EnumPropertyItem direction_items[]= {
|
||||
{DIRECTION_CW, "CW", 0, "Clockwise", ""},
|
||||
@@ -2061,16 +2061,40 @@ void MESH_OT_faces_shade_flat(wmOperatorType *ot)
|
||||
|
||||
|
||||
/********************** UV/Color Operators *************************/
|
||||
#define AXIS_X 1
|
||||
#define AXIS_Y 2
|
||||
|
||||
|
||||
static const EnumPropertyItem axis_items[]= {
|
||||
{AXIS_X, "X", 0, "X", ""},
|
||||
{AXIS_Y, "Y", 0, "Y", ""},
|
||||
{OPUVC_AXIS_X, "X", 0, "X", ""},
|
||||
{OPUVC_AXIS_Y, "Y", 0, "Y", ""},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static int mesh_rotate_uvs(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *ob = CTX_data_edit_object(C);
|
||||
BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
|
||||
BMOperator bmop;
|
||||
|
||||
/* get the direction from RNA */
|
||||
int dir = RNA_enum_get(op->ptr, "direction");
|
||||
|
||||
/* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
|
||||
EDBM_InitOpf(em, &bmop, op, "meshrotateuvs faces=%hf dir=%d", BM_SELECT, dir);
|
||||
|
||||
/* execute the operator */
|
||||
BMO_Exec_Op(em->bm, &bmop);
|
||||
|
||||
/* finish the operator */
|
||||
if( !EDBM_FinishOp(em, &bmop, op, 1) )
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
|
||||
/* dependencies graph and notification stuff */
|
||||
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_GEOM_SELECT, ob);
|
||||
|
||||
/* we succeeded */
|
||||
return OPERATOR_FINISHED;
|
||||
#if 0
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
|
||||
@@ -340,9 +340,9 @@ void make_vertexcol(Scene *scene, int shade) /* single ob */
|
||||
|
||||
/* copies from shadedisplist to mcol */
|
||||
if(!me->mcol)
|
||||
CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface);
|
||||
CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface);
|
||||
if (!me->mloopcol)
|
||||
CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, me->totloop);
|
||||
CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop);
|
||||
|
||||
mesh_update_customdata_pointers(me);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user