forked from bartvdbraak/blender
vertex color rotation and reversing/shortest vertex path
This commit is contained in:
parent
f0ff8d665d
commit
c75e1598dd
@ -60,6 +60,12 @@ enum {
|
|||||||
DIRECTION_CCW
|
DIRECTION_CCW
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* vertex path selection values */
|
||||||
|
enum {
|
||||||
|
VPATH_SELECT_EDGE_LENGTH = 0,
|
||||||
|
VPATH_SELECT_TOPOLOGICAL
|
||||||
|
};
|
||||||
|
|
||||||
extern BMOpDefine *opdefines[];
|
extern BMOpDefine *opdefines[];
|
||||||
extern int bmesh_total_ops;
|
extern int bmesh_total_ops;
|
||||||
|
|
||||||
|
@ -761,6 +761,47 @@ BMOpDefine def_meshreverseuvs = {
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** color rotation
|
||||||
|
** cycle the colors
|
||||||
|
*/
|
||||||
|
BMOpDefine def_meshrotatecolors = {
|
||||||
|
"meshrotatecolors",
|
||||||
|
{{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, /* input faces */
|
||||||
|
{BMOP_OPSLOT_INT, "dir"}, /* direction */
|
||||||
|
{0} /*null-terminating sentinel*/},
|
||||||
|
bmesh_rotatecolors_exec,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** color reverse
|
||||||
|
** reverse the colors
|
||||||
|
*/
|
||||||
|
BMOpDefine def_meshreversecolors = {
|
||||||
|
"meshreversecolors",
|
||||||
|
{{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, /* input faces */
|
||||||
|
{0} /*null-terminating sentinel*/},
|
||||||
|
bmesh_reversecolors_exec,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Similar vertices select
|
||||||
|
|
||||||
|
Select similar vertices (normal, face, vertex group,....).
|
||||||
|
*/
|
||||||
|
BMOpDefine def_vertexshortestpath = {
|
||||||
|
"vertexshortestpath",
|
||||||
|
{{BMOP_OPSLOT_ELEMENT_BUF, "startv"}, /* start vertex */
|
||||||
|
{BMOP_OPSLOT_ELEMENT_BUF, "endv"}, /* end vertex */
|
||||||
|
{BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, /* output vertices */
|
||||||
|
{BMOP_OPSLOT_INT, "type"}, /* type of selection */
|
||||||
|
{0} /*null-terminating sentinel*/},
|
||||||
|
bmesh_vertexshortestpath_exec,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
BMOpDefine *opdefines[] = {
|
BMOpDefine *opdefines[] = {
|
||||||
&def_splitop,
|
&def_splitop,
|
||||||
&def_dupeop,
|
&def_dupeop,
|
||||||
@ -810,6 +851,9 @@ BMOpDefine *opdefines[] = {
|
|||||||
&def_bmesh_to_mesh,
|
&def_bmesh_to_mesh,
|
||||||
&def_meshreverseuvs,
|
&def_meshreverseuvs,
|
||||||
&def_edgenet_prepare,
|
&def_edgenet_prepare,
|
||||||
|
&def_meshrotatecolors,
|
||||||
|
&def_meshreversecolors,
|
||||||
|
&def_vertexshortestpath,
|
||||||
&def_scale,
|
&def_scale,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,6 +55,8 @@ void bmesh_rotateuvs_exec(BMesh *bm, BMOperator *op);
|
|||||||
void object_load_bmesh_exec(BMesh *bm, BMOperator *op);
|
void object_load_bmesh_exec(BMesh *bm, BMOperator *op);
|
||||||
void bmesh_reverseuvs_exec(BMesh *bm, BMOperator *op);
|
void bmesh_reverseuvs_exec(BMesh *bm, BMOperator *op);
|
||||||
void bmesh_edgenet_prepare(BMesh *bm, BMOperator *op);
|
void bmesh_edgenet_prepare(BMesh *bm, BMOperator *op);
|
||||||
|
void bmesh_rotatecolors_exec(BMesh *bm, BMOperator *op);
|
||||||
|
void bmesh_reversecolors_exec(BMesh *bm, BMOperator *op);
|
||||||
|
void bmesh_vertexshortestpath_exec(BMesh *bm, BMOperator *op);
|
||||||
void bmesh_scale_exec(BMesh *bm, BMOperator *op);
|
void bmesh_scale_exec(BMesh *bm, BMOperator *op);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include "BLI_blenlib.h"
|
#include "BLI_blenlib.h"
|
||||||
#include "BLI_edgehash.h"
|
#include "BLI_edgehash.h"
|
||||||
|
|
||||||
|
#include "BLI_heap.h"
|
||||||
|
|
||||||
#include "bmesh.h"
|
#include "bmesh.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1081,3 +1083,218 @@ void bmesh_reverseuvs_exec(BMesh *bm, BMOperator *op)
|
|||||||
|
|
||||||
BLI_array_free(uvs);
|
BLI_array_free(uvs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
** Cycle colors for a face
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
void bmesh_rotatecolors_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_MLOOPCOL) ) {
|
||||||
|
if( dir == DIRECTION_CW ) { /* same loops direction */
|
||||||
|
BMLoop *lf; /* current face loops */
|
||||||
|
MLoopCol *f_lcol; /* first face loop color */
|
||||||
|
MLoopCol p_col; /* previous color */
|
||||||
|
MLoopCol t_col; /* tmp color */
|
||||||
|
|
||||||
|
int n = 0;
|
||||||
|
BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
|
||||||
|
/* current loop color is the previous loop color */
|
||||||
|
MLoopCol *luv = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPCOL);
|
||||||
|
if( n == 0 ) {
|
||||||
|
f_lcol = luv;
|
||||||
|
p_col = *luv;
|
||||||
|
} else {
|
||||||
|
t_col = *luv;
|
||||||
|
*luv = p_col;
|
||||||
|
p_col = t_col;
|
||||||
|
}
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*f_lcol = p_col;
|
||||||
|
} else if( dir == DIRECTION_CCW ) { /* counter loop direction */
|
||||||
|
BMLoop *lf; /* current face loops */
|
||||||
|
MLoopCol *p_lcol; /*previous loop color */
|
||||||
|
MLoopCol *lcol;
|
||||||
|
MLoopCol t_col; /* current color */
|
||||||
|
|
||||||
|
int n = 0;
|
||||||
|
BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
|
||||||
|
/* previous loop color is the current loop color */
|
||||||
|
lcol = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPCOL);
|
||||||
|
if( n == 0 ) {
|
||||||
|
p_lcol = lcol;
|
||||||
|
t_col = *lcol;
|
||||||
|
} else {
|
||||||
|
*p_lcol = *lcol;
|
||||||
|
p_lcol = lcol;
|
||||||
|
}
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*lcol = t_col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
** Reverse colors for a face
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
void bmesh_reversecolors_exec(BMesh *bm, BMOperator *op)
|
||||||
|
{
|
||||||
|
BMOIter fs_iter; /* selected faces iterator */
|
||||||
|
BMFace *fs; /* current face */
|
||||||
|
BMIter l_iter; /* iteration loop */
|
||||||
|
BLI_array_declare(cols);
|
||||||
|
MLoopCol *cols = NULL;
|
||||||
|
int max_vert_count = 0;
|
||||||
|
|
||||||
|
|
||||||
|
BMO_ITER(fs, &fs_iter, bm, op, "faces", BM_FACE) {
|
||||||
|
if( CustomData_has_layer(&(bm->ldata), CD_MLOOPCOL) ) {
|
||||||
|
BMLoop *lf; /* current face loops */
|
||||||
|
MLoopCol *f_lcol; /* first face loop color */
|
||||||
|
int num_verts = fs->len;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
BLI_array_empty(cols);
|
||||||
|
BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
|
||||||
|
MLoopCol *lcol = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPCOL);
|
||||||
|
|
||||||
|
/* current loop uv is the previous loop color */
|
||||||
|
BLI_array_growone(cols);
|
||||||
|
cols[i] = *lcol;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now that we have the uvs in the array, reverse! */
|
||||||
|
i = 0;
|
||||||
|
BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
|
||||||
|
/* current loop uv is the previous loop color */
|
||||||
|
MLoopCol *lcol = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPCOL);
|
||||||
|
*lcol = cols[(fs->len - i - 1)];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_array_free(cols);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
** shortest vertex path select
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
typedef struct element_node {
|
||||||
|
BMVert *v; /* vertex */
|
||||||
|
BMVert *parent; /* node parent id */
|
||||||
|
float weight; /* node weight */
|
||||||
|
HeapNode *hn; /* heap node */
|
||||||
|
} element_node;
|
||||||
|
|
||||||
|
void bmesh_vertexshortestpath_exec(BMesh *bm, BMOperator *op)
|
||||||
|
{
|
||||||
|
BMOIter vs_iter, vs2_iter; /* selected verts iterator */
|
||||||
|
BMIter v_iter; /* mesh verts iterator */
|
||||||
|
BMVert *vs, *sv, *ev; /* starting vertex, ending vertex */
|
||||||
|
BMVert *v; /* mesh vertex */
|
||||||
|
Heap *h = NULL;
|
||||||
|
|
||||||
|
element_node *vert_list = NULL;
|
||||||
|
|
||||||
|
int num_total = 0, num_sels = 0, i = 0;
|
||||||
|
int type = BMO_Get_Int(op, "type");
|
||||||
|
|
||||||
|
BMO_ITER(vs, &vs_iter, bm, op, "startv", BM_VERT)
|
||||||
|
sv = vs;
|
||||||
|
BMO_ITER(vs, &vs_iter, bm, op, "endv", BM_VERT)
|
||||||
|
ev = vs;
|
||||||
|
|
||||||
|
num_total = BM_Count_Element(bm, BM_VERT);
|
||||||
|
|
||||||
|
/* allocate memory for the nodes */
|
||||||
|
vert_list = (element_node*)MEM_mallocN(sizeof(element_node) * num_total, "vertex nodes");
|
||||||
|
|
||||||
|
/* iterate through all the mesh vertices */
|
||||||
|
/* loop through all the vertices and fill the vertices/indices structure */
|
||||||
|
i = 0;
|
||||||
|
BM_ITER(v, &v_iter, bm, BM_VERTS_OF_MESH, NULL) {
|
||||||
|
vert_list[i].v = v;
|
||||||
|
vert_list[i].parent = NULL;
|
||||||
|
vert_list[i].weight = FLT_MAX;
|
||||||
|
BMINDEX_SET(v, i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** we now have everything we need, start Dijkstra path finding algorithm
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* set the distance/weight of the start vertex to 0 */
|
||||||
|
vert_list[BMINDEX_GET(sv)].weight = 0.0f;
|
||||||
|
|
||||||
|
h = BLI_heap_new();
|
||||||
|
|
||||||
|
for( i = 0; i < num_total; i++ )
|
||||||
|
vert_list[i].hn = BLI_heap_insert(h, vert_list[i].weight, vert_list[i].v);
|
||||||
|
|
||||||
|
while( !BLI_heap_empty(h) ) {
|
||||||
|
BMEdge *e;
|
||||||
|
BMIter e_i;
|
||||||
|
float v_weight;
|
||||||
|
|
||||||
|
/* take the vertex with the lowest weight out of the heap */
|
||||||
|
BMVert *v = (BMVert*)BLI_heap_popmin(h);
|
||||||
|
|
||||||
|
if( vert_list[BMINDEX_GET(v)].weight == FLT_MAX ) /* this means that there is no path */
|
||||||
|
break;
|
||||||
|
|
||||||
|
v_weight = vert_list[BMINDEX_GET(v)].weight;
|
||||||
|
|
||||||
|
BM_ITER(e, &e_i, bm, BM_EDGES_OF_VERT, v) {
|
||||||
|
BMVert *u;
|
||||||
|
float e_weight = v_weight;
|
||||||
|
|
||||||
|
if( type == VPATH_SELECT_EDGE_LENGTH )
|
||||||
|
e_weight += VecLenf(e->v1->co, e->v2->co);
|
||||||
|
else e_weight += 1.0f;
|
||||||
|
|
||||||
|
u = ( e->v1 == v ) ? e->v2 : e->v1;
|
||||||
|
|
||||||
|
if( e_weight < vert_list[BMINDEX_GET(u)].weight ) { /* is this path shorter ? */
|
||||||
|
/* add it if so */
|
||||||
|
vert_list[BMINDEX_GET(u)].parent = v;
|
||||||
|
vert_list[BMINDEX_GET(u)].weight = e_weight;
|
||||||
|
|
||||||
|
/* we should do a heap update node function!!! :-/ */
|
||||||
|
BLI_heap_remove(h, vert_list[BMINDEX_GET(u)].hn);
|
||||||
|
BLI_heap_insert(h, e_weight, u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now we trace the path (if it exists) */
|
||||||
|
v = ev;
|
||||||
|
|
||||||
|
while( vert_list[BMINDEX_GET(v)].parent != NULL ) {
|
||||||
|
BMO_SetFlag(bm, v, VERT_MARK);
|
||||||
|
v = vert_list[BMINDEX_GET(v)].parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_heap_free(h, NULL);
|
||||||
|
MEM_freeN(vert_list);
|
||||||
|
|
||||||
|
BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT);
|
||||||
|
}
|
||||||
|
@ -2215,7 +2215,9 @@ static int mesh_rotate_uvs(bContext *C, wmOperator *op)
|
|||||||
/* dependencies graph and notification stuff */
|
/* dependencies graph and notification stuff */
|
||||||
DAG_id_flush_update(ob->data, OB_RECALC_DATA);
|
DAG_id_flush_update(ob->data, OB_RECALC_DATA);
|
||||||
WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
|
WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
|
||||||
|
/* DAG_id_flush_update(ob->data, OB_RECALC_DATA);
|
||||||
|
WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
|
||||||
|
*/
|
||||||
/* we succeeded */
|
/* we succeeded */
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
@ -2240,73 +2242,67 @@ static int mesh_reverse_uvs(bContext *C, wmOperator *op)
|
|||||||
/* dependencies graph and notification stuff */
|
/* dependencies graph and notification stuff */
|
||||||
DAG_id_flush_update(ob->data, OB_RECALC_DATA);
|
DAG_id_flush_update(ob->data, OB_RECALC_DATA);
|
||||||
WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
|
WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
|
||||||
|
/* DAG_id_flush_update(ob->data, OB_RECALC_DATA);
|
||||||
|
WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
|
||||||
|
*/
|
||||||
/* we succeeded */
|
/* we succeeded */
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mesh_rotate_colors(bContext *C, wmOperator *op)
|
static int mesh_rotate_colors(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
#if 0
|
Scene *scene = CTX_data_scene(C);
|
||||||
Scene *scene= CTX_data_scene(C);
|
Object *ob = CTX_data_edit_object(C);
|
||||||
Object *obedit= CTX_data_edit_object(C);
|
BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
|
||||||
EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
|
BMOperator bmop;
|
||||||
|
|
||||||
EditFace *efa;
|
/* get the direction from RNA */
|
||||||
short change = 0;
|
int dir = RNA_enum_get(op->ptr, "direction");
|
||||||
MCol tmpcol, *mcol;
|
|
||||||
int dir= RNA_enum_get(op->ptr, "direction");
|
|
||||||
|
|
||||||
if (!EM_vertColorCheck(em)) {
|
/* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
|
||||||
BKE_report(op->reports, RPT_ERROR, "Mesh has no color layers.");
|
EDBM_InitOpf(em, &bmop, op, "meshrotatecolors faces=%hf dir=%d", BM_SELECT, dir);
|
||||||
BKE_mesh_end_editmesh(obedit->data, em);
|
|
||||||
return OPERATOR_CANCELLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(efa=em->faces.first; efa; efa=efa->next) {
|
/* execute the operator */
|
||||||
if (efa->f & SELECT) {
|
BMO_Exec_Op(em->bm, &bmop);
|
||||||
mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
|
|
||||||
tmpcol= mcol[0];
|
|
||||||
|
|
||||||
if (dir == DIRECTION_CCW) {
|
/* finish the operator */
|
||||||
if(efa->v4) {
|
if( !EDBM_FinishOp(em, &bmop, op, 1) )
|
||||||
mcol[0]= mcol[3];
|
|
||||||
mcol[3]= mcol[2];
|
|
||||||
} else {
|
|
||||||
mcol[0]= mcol[2];
|
|
||||||
}
|
|
||||||
mcol[2]= mcol[1];
|
|
||||||
mcol[1]= tmpcol;
|
|
||||||
} else {
|
|
||||||
mcol[0]= mcol[1];
|
|
||||||
mcol[1]= mcol[2];
|
|
||||||
|
|
||||||
if(efa->v4) {
|
|
||||||
mcol[2]= mcol[3];
|
|
||||||
mcol[3]= tmpcol;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mcol[2]= tmpcol;
|
|
||||||
}
|
|
||||||
change = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BKE_mesh_end_editmesh(obedit->data, em);
|
|
||||||
|
|
||||||
if(!change)
|
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
|
|
||||||
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
|
|
||||||
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
|
|
||||||
|
|
||||||
|
/* dependencies graph and notification stuff */
|
||||||
|
DAG_id_flush_update(ob->data, OB_RECALC_DATA);
|
||||||
|
WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
|
||||||
|
/* 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;
|
return OPERATOR_FINISHED;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int mesh_mirror_colors(bContext *C, wmOperator *op)
|
static int mesh_reverse_colors(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;
|
||||||
|
|
||||||
|
/* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
|
||||||
|
EDBM_InitOpf(em, &bmop, op, "meshreversecolors faces=%hf", BM_SELECT);
|
||||||
|
|
||||||
|
/* execute the operator */
|
||||||
|
BMO_Exec_Op(em->bm, &bmop);
|
||||||
|
|
||||||
|
/* finish the operator */
|
||||||
|
if( !EDBM_FinishOp(em, &bmop, op, 1) )
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
|
||||||
|
DAG_id_flush_update(ob->data, OB_RECALC_DATA);
|
||||||
|
WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
|
||||||
|
|
||||||
|
/* we succeeded */
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
#if 0
|
#if 0
|
||||||
Scene *scene= CTX_data_scene(C);
|
Scene *scene= CTX_data_scene(C);
|
||||||
Object *obedit= CTX_data_edit_object(C);
|
Object *obedit= CTX_data_edit_object(C);
|
||||||
@ -2415,21 +2411,21 @@ void MESH_OT_colors_rotate(wmOperatorType *ot)
|
|||||||
RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate edge around.");
|
RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate edge around.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MESH_OT_colors_mirror(wmOperatorType *ot)
|
void MESH_OT_colors_reverse(wmOperatorType *ot)
|
||||||
{
|
{
|
||||||
/* identifiers */
|
/* identifiers */
|
||||||
ot->name= "Mirror Colors";
|
ot->name= "Reverse Colors";
|
||||||
ot->idname= "MESH_OT_colors_mirror";
|
ot->idname= "MESH_OT_colors_reverse";
|
||||||
|
|
||||||
/* api callbacks */
|
/* api callbacks */
|
||||||
ot->exec= mesh_mirror_colors;
|
ot->exec= mesh_reverse_colors;
|
||||||
ot->poll= ED_operator_editmesh;
|
ot->poll= ED_operator_editmesh;
|
||||||
|
|
||||||
/* flags */
|
/* flags */
|
||||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||||
|
|
||||||
/* props */
|
/* props */
|
||||||
RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around.");
|
//RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2666,3 +2662,249 @@ void MESH_OT_remove_doubles(wmOperatorType *ot)
|
|||||||
"Merge Distance",
|
"Merge Distance",
|
||||||
"Minimum distance between elements to merge.", 0.00001, 10.0);
|
"Minimum distance between elements to merge.", 0.00001, 10.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************ Vertex Path Operator *************************/
|
||||||
|
|
||||||
|
typedef struct PathNode {
|
||||||
|
int u;
|
||||||
|
int visited;
|
||||||
|
ListBase edges;
|
||||||
|
} PathNode;
|
||||||
|
|
||||||
|
typedef struct PathEdge {
|
||||||
|
struct PathEdge *next, *prev;
|
||||||
|
int v;
|
||||||
|
float w;
|
||||||
|
} PathEdge;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int select_vertex_path_exec(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;
|
||||||
|
BMEditSelection *sv, *ev;
|
||||||
|
|
||||||
|
/* get the type from RNA */
|
||||||
|
int type = RNA_enum_get(op->ptr, "type");
|
||||||
|
|
||||||
|
sv = em->bm->selected.last;
|
||||||
|
if( sv != NULL )
|
||||||
|
ev = sv->prev;
|
||||||
|
else return OPERATOR_CANCELLED;
|
||||||
|
if( ev == NULL )
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
|
||||||
|
if( sv->type != BM_VERT || ev->type != BM_VERT )
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
|
||||||
|
/* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
|
||||||
|
EDBM_InitOpf(em, &bmop, op, "vertexshortestpath startv=%e endv=%e type=%d", sv->data, ev->data, type);
|
||||||
|
|
||||||
|
/* execute the operator */
|
||||||
|
BMO_Exec_Op(em->bm, &bmop);
|
||||||
|
|
||||||
|
/* DO NOT clear the existing selection */
|
||||||
|
/* EDBM_clear_flag_all(em, BM_SELECT); */
|
||||||
|
|
||||||
|
/* select the output */
|
||||||
|
BMO_HeaderFlag_Buffer(em->bm, &bmop, "vertout", BM_SELECT, BM_ALL);
|
||||||
|
|
||||||
|
/* finish the operator */
|
||||||
|
if( !EDBM_FinishOp(em, &bmop, op, 1) )
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
|
||||||
|
EDBM_selectmode_flush(em);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
*/
|
||||||
|
DAG_id_flush_update(ob->data, OB_RECALC_DATA);
|
||||||
|
WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
|
||||||
|
|
||||||
|
|
||||||
|
/* we succeeded */
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
#if 0
|
||||||
|
Object *obedit= CTX_data_edit_object(C);
|
||||||
|
EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
|
||||||
|
EditVert *eve, *s, *t;
|
||||||
|
EditEdge *eed;
|
||||||
|
EditSelection *ese;
|
||||||
|
PathEdge *newpe, *currpe;
|
||||||
|
PathNode *currpn;
|
||||||
|
PathNode *Q;
|
||||||
|
int v, *previous, pathvert, pnindex; /*pnindex redundant?*/
|
||||||
|
int unbalanced, totnodes;
|
||||||
|
short physical;
|
||||||
|
float *cost;
|
||||||
|
Heap *heap; /*binary heap for sorting pointers to PathNodes based upon a 'cost'*/
|
||||||
|
|
||||||
|
s = t = NULL;
|
||||||
|
|
||||||
|
ese = ((EditSelection*)em->selected.last);
|
||||||
|
if(ese && ese->type == EDITVERT && ese->prev && ese->prev->type == EDITVERT){
|
||||||
|
physical= pupmenu("Distance Method? %t|Edge Length%x1|Topological%x0");
|
||||||
|
|
||||||
|
t = (EditVert*)ese->data;
|
||||||
|
s = (EditVert*)ese->prev->data;
|
||||||
|
|
||||||
|
/*need to find out if t is actually reachable by s....*/
|
||||||
|
for(eve=em->verts.first; eve; eve=eve->next){
|
||||||
|
eve->f1 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->f1 = 1;
|
||||||
|
|
||||||
|
unbalanced = 1;
|
||||||
|
totnodes = 1;
|
||||||
|
while(unbalanced){
|
||||||
|
unbalanced = 0;
|
||||||
|
for(eed=em->edges.first; eed; eed=eed->next){
|
||||||
|
if(!eed->h){
|
||||||
|
if(eed->v1->f1 && !eed->v2->f1){
|
||||||
|
eed->v2->f1 = 1;
|
||||||
|
totnodes++;
|
||||||
|
unbalanced = 1;
|
||||||
|
}
|
||||||
|
else if(eed->v2->f1 && !eed->v1->f1){
|
||||||
|
eed->v1->f1 = 1;
|
||||||
|
totnodes++;
|
||||||
|
unbalanced = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(s->f1 && t->f1){ /* t can be reached by s */
|
||||||
|
Q = MEM_callocN(sizeof(PathNode)*totnodes, "Path Select Nodes");
|
||||||
|
totnodes = 0;
|
||||||
|
for(eve=em->verts.first; eve; eve=eve->next){
|
||||||
|
if(eve->f1){
|
||||||
|
Q[totnodes].u = totnodes;
|
||||||
|
Q[totnodes].edges.first = 0;
|
||||||
|
Q[totnodes].edges.last = 0;
|
||||||
|
Q[totnodes].visited = 0;
|
||||||
|
eve->tmp.p = &(Q[totnodes]);
|
||||||
|
totnodes++;
|
||||||
|
}
|
||||||
|
else eve->tmp.p = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(eed=em->edges.first; eed; eed=eed->next){
|
||||||
|
if(!eed->h){
|
||||||
|
if(eed->v1->f1){
|
||||||
|
currpn = ((PathNode*)eed->v1->tmp.p);
|
||||||
|
|
||||||
|
newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge");
|
||||||
|
newpe->v = ((PathNode*)eed->v2->tmp.p)->u;
|
||||||
|
if(physical){
|
||||||
|
newpe->w = VecLenf(eed->v1->co, eed->v2->co);
|
||||||
|
}
|
||||||
|
else newpe->w = 1;
|
||||||
|
newpe->next = 0;
|
||||||
|
newpe->prev = 0;
|
||||||
|
BLI_addtail(&(currpn->edges), newpe);
|
||||||
|
}
|
||||||
|
if(eed->v2->f1){
|
||||||
|
currpn = ((PathNode*)eed->v2->tmp.p);
|
||||||
|
newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge");
|
||||||
|
newpe->v = ((PathNode*)eed->v1->tmp.p)->u;
|
||||||
|
if(physical){
|
||||||
|
newpe->w = VecLenf(eed->v1->co, eed->v2->co);
|
||||||
|
}
|
||||||
|
else newpe->w = 1;
|
||||||
|
newpe->next = 0;
|
||||||
|
newpe->prev = 0;
|
||||||
|
BLI_addtail(&(currpn->edges), newpe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
heap = BLI_heap_new();
|
||||||
|
cost = MEM_callocN(sizeof(float)*totnodes, "Path Select Costs");
|
||||||
|
previous = MEM_callocN(sizeof(int)*totnodes, "PathNode indices");
|
||||||
|
|
||||||
|
for(v=0; v < totnodes; v++){
|
||||||
|
cost[v] = 1000000;
|
||||||
|
previous[v] = -1; /*array of indices*/
|
||||||
|
}
|
||||||
|
|
||||||
|
pnindex = ((PathNode*)s->tmp.p)->u;
|
||||||
|
cost[pnindex] = 0;
|
||||||
|
BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(pnindex));
|
||||||
|
|
||||||
|
while( !BLI_heap_empty(heap) ){
|
||||||
|
|
||||||
|
pnindex = GET_INT_FROM_POINTER(BLI_heap_popmin(heap));
|
||||||
|
currpn = &(Q[pnindex]);
|
||||||
|
|
||||||
|
if(currpn == (PathNode*)t->tmp.p) /*target has been reached....*/
|
||||||
|
break;
|
||||||
|
|
||||||
|
for(currpe=currpn->edges.first; currpe; currpe=currpe->next){
|
||||||
|
if(!Q[currpe->v].visited){
|
||||||
|
if( cost[currpe->v] > (cost[currpn->u ] + currpe->w) ){
|
||||||
|
cost[currpe->v] = cost[currpn->u] + currpe->w;
|
||||||
|
previous[currpe->v] = currpn->u;
|
||||||
|
Q[currpe->v].visited = 1;
|
||||||
|
BLI_heap_insert(heap, cost[currpe->v], SET_INT_IN_POINTER(currpe->v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pathvert = ((PathNode*)t->tmp.p)->u;
|
||||||
|
while(pathvert != -1){
|
||||||
|
for(eve=em->verts.first; eve; eve=eve->next){
|
||||||
|
if(eve->f1){
|
||||||
|
if( ((PathNode*)eve->tmp.p)->u == pathvert) eve->f |= SELECT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pathvert = previous[pathvert];
|
||||||
|
}
|
||||||
|
|
||||||
|
for(v=0; v < totnodes; v++) BLI_freelistN(&(Q[v].edges));
|
||||||
|
MEM_freeN(Q);
|
||||||
|
MEM_freeN(cost);
|
||||||
|
MEM_freeN(previous);
|
||||||
|
BLI_heap_free(heap, NULL);
|
||||||
|
EM_select_flush(em);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BKE_mesh_end_editmesh(obedit->data, em);
|
||||||
|
BKE_report(op->reports, RPT_ERROR, "Path Selection requires that exactly two vertices be selected");
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
|
||||||
|
BKE_mesh_end_editmesh(obedit->data, em);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void MESH_OT_select_vertex_path(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
static const EnumPropertyItem type_items[] = {
|
||||||
|
{VPATH_SELECT_EDGE_LENGTH, "EDGE_LENGTH", 0, "Edge Length", NULL},
|
||||||
|
{VPATH_SELECT_TOPOLOGICAL, "TOPOLOGICAL", 0, "Topological", NULL},
|
||||||
|
{0, NULL, 0, NULL, NULL}};
|
||||||
|
|
||||||
|
/* identifiers */
|
||||||
|
ot->name= "Select Vertex Path";
|
||||||
|
ot->idname= "MESH_OT_select_vertex_path";
|
||||||
|
|
||||||
|
/* api callbacks */
|
||||||
|
ot->exec= select_vertex_path_exec;
|
||||||
|
ot->invoke= WM_menu_invoke;
|
||||||
|
ot->poll= ED_operator_editmesh;
|
||||||
|
|
||||||
|
/* flags */
|
||||||
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
RNA_def_enum(ot->srna, "type", type_items, VPATH_SELECT_EDGE_LENGTH, "Type", "Method to compute distance.");
|
||||||
|
}
|
||||||
|
@ -5198,205 +5198,7 @@ int collapseEdges(EditMesh *em)
|
|||||||
return mergecount;
|
return mergecount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************ Vertex Path Operator *************************/
|
|
||||||
|
|
||||||
typedef struct PathNode {
|
|
||||||
int u;
|
|
||||||
int visited;
|
|
||||||
ListBase edges;
|
|
||||||
} PathNode;
|
|
||||||
|
|
||||||
typedef struct PathEdge {
|
|
||||||
struct PathEdge *next, *prev;
|
|
||||||
int v;
|
|
||||||
float w;
|
|
||||||
} PathEdge;
|
|
||||||
|
|
||||||
#define PATH_SELECT_EDGE_LENGTH 0
|
|
||||||
#define PATH_SELECT_TOPOLOGICAL 1
|
|
||||||
|
|
||||||
int select_vertex_path_exec(bContext *C, wmOperator *op)
|
|
||||||
{
|
|
||||||
Object *obedit= CTX_data_edit_object(C);
|
|
||||||
EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
|
|
||||||
EditVert *eve, *s, *t;
|
|
||||||
EditEdge *eed;
|
|
||||||
EditSelection *ese;
|
|
||||||
PathEdge *newpe, *currpe;
|
|
||||||
PathNode *currpn;
|
|
||||||
PathNode *Q;
|
|
||||||
int v, *previous, pathvert, pnindex; /*pnindex redundant?*/
|
|
||||||
int unbalanced, totnodes;
|
|
||||||
short physical;
|
|
||||||
float *cost;
|
|
||||||
Heap *heap; /*binary heap for sorting pointers to PathNodes based upon a 'cost'*/
|
|
||||||
|
|
||||||
s = t = NULL;
|
|
||||||
|
|
||||||
ese = ((EditSelection*)em->selected.last);
|
|
||||||
if(ese && ese->type == EDITVERT && ese->prev && ese->prev->type == EDITVERT){
|
|
||||||
physical= pupmenu("Distance Method? %t|Edge Length%x1|Topological%x0");
|
|
||||||
|
|
||||||
t = (EditVert*)ese->data;
|
|
||||||
s = (EditVert*)ese->prev->data;
|
|
||||||
|
|
||||||
/*need to find out if t is actually reachable by s....*/
|
|
||||||
for(eve=em->verts.first; eve; eve=eve->next){
|
|
||||||
eve->f1 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
s->f1 = 1;
|
|
||||||
|
|
||||||
unbalanced = 1;
|
|
||||||
totnodes = 1;
|
|
||||||
while(unbalanced){
|
|
||||||
unbalanced = 0;
|
|
||||||
for(eed=em->edges.first; eed; eed=eed->next){
|
|
||||||
if(!eed->h){
|
|
||||||
if(eed->v1->f1 && !eed->v2->f1){
|
|
||||||
eed->v2->f1 = 1;
|
|
||||||
totnodes++;
|
|
||||||
unbalanced = 1;
|
|
||||||
}
|
|
||||||
else if(eed->v2->f1 && !eed->v1->f1){
|
|
||||||
eed->v1->f1 = 1;
|
|
||||||
totnodes++;
|
|
||||||
unbalanced = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(s->f1 && t->f1){ /* t can be reached by s */
|
|
||||||
Q = MEM_callocN(sizeof(PathNode)*totnodes, "Path Select Nodes");
|
|
||||||
totnodes = 0;
|
|
||||||
for(eve=em->verts.first; eve; eve=eve->next){
|
|
||||||
if(eve->f1){
|
|
||||||
Q[totnodes].u = totnodes;
|
|
||||||
Q[totnodes].edges.first = 0;
|
|
||||||
Q[totnodes].edges.last = 0;
|
|
||||||
Q[totnodes].visited = 0;
|
|
||||||
eve->tmp.p = &(Q[totnodes]);
|
|
||||||
totnodes++;
|
|
||||||
}
|
|
||||||
else eve->tmp.p = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(eed=em->edges.first; eed; eed=eed->next){
|
|
||||||
if(!eed->h){
|
|
||||||
if(eed->v1->f1){
|
|
||||||
currpn = ((PathNode*)eed->v1->tmp.p);
|
|
||||||
|
|
||||||
newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge");
|
|
||||||
newpe->v = ((PathNode*)eed->v2->tmp.p)->u;
|
|
||||||
if(physical){
|
|
||||||
newpe->w = VecLenf(eed->v1->co, eed->v2->co);
|
|
||||||
}
|
|
||||||
else newpe->w = 1;
|
|
||||||
newpe->next = 0;
|
|
||||||
newpe->prev = 0;
|
|
||||||
BLI_addtail(&(currpn->edges), newpe);
|
|
||||||
}
|
|
||||||
if(eed->v2->f1){
|
|
||||||
currpn = ((PathNode*)eed->v2->tmp.p);
|
|
||||||
newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge");
|
|
||||||
newpe->v = ((PathNode*)eed->v1->tmp.p)->u;
|
|
||||||
if(physical){
|
|
||||||
newpe->w = VecLenf(eed->v1->co, eed->v2->co);
|
|
||||||
}
|
|
||||||
else newpe->w = 1;
|
|
||||||
newpe->next = 0;
|
|
||||||
newpe->prev = 0;
|
|
||||||
BLI_addtail(&(currpn->edges), newpe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
heap = BLI_heap_new();
|
|
||||||
cost = MEM_callocN(sizeof(float)*totnodes, "Path Select Costs");
|
|
||||||
previous = MEM_callocN(sizeof(int)*totnodes, "PathNode indices");
|
|
||||||
|
|
||||||
for(v=0; v < totnodes; v++){
|
|
||||||
cost[v] = 1000000;
|
|
||||||
previous[v] = -1; /*array of indices*/
|
|
||||||
}
|
|
||||||
|
|
||||||
pnindex = ((PathNode*)s->tmp.p)->u;
|
|
||||||
cost[pnindex] = 0;
|
|
||||||
BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(pnindex));
|
|
||||||
|
|
||||||
while( !BLI_heap_empty(heap) ){
|
|
||||||
|
|
||||||
pnindex = GET_INT_FROM_POINTER(BLI_heap_popmin(heap));
|
|
||||||
currpn = &(Q[pnindex]);
|
|
||||||
|
|
||||||
if(currpn == (PathNode*)t->tmp.p) /*target has been reached....*/
|
|
||||||
break;
|
|
||||||
|
|
||||||
for(currpe=currpn->edges.first; currpe; currpe=currpe->next){
|
|
||||||
if(!Q[currpe->v].visited){
|
|
||||||
if( cost[currpe->v] > (cost[currpn->u ] + currpe->w) ){
|
|
||||||
cost[currpe->v] = cost[currpn->u] + currpe->w;
|
|
||||||
previous[currpe->v] = currpn->u;
|
|
||||||
Q[currpe->v].visited = 1;
|
|
||||||
BLI_heap_insert(heap, cost[currpe->v], SET_INT_IN_POINTER(currpe->v));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pathvert = ((PathNode*)t->tmp.p)->u;
|
|
||||||
while(pathvert != -1){
|
|
||||||
for(eve=em->verts.first; eve; eve=eve->next){
|
|
||||||
if(eve->f1){
|
|
||||||
if( ((PathNode*)eve->tmp.p)->u == pathvert) eve->f |= SELECT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pathvert = previous[pathvert];
|
|
||||||
}
|
|
||||||
|
|
||||||
for(v=0; v < totnodes; v++) BLI_freelistN(&(Q[v].edges));
|
|
||||||
MEM_freeN(Q);
|
|
||||||
MEM_freeN(cost);
|
|
||||||
MEM_freeN(previous);
|
|
||||||
BLI_heap_free(heap, NULL);
|
|
||||||
EM_select_flush(em);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
BKE_mesh_end_editmesh(obedit->data, em);
|
|
||||||
BKE_report(op->reports, RPT_ERROR, "Path Selection requires that exactly two vertices be selected");
|
|
||||||
return OPERATOR_CANCELLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
|
|
||||||
BKE_mesh_end_editmesh(obedit->data, em);
|
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MESH_OT_select_vertex_path(wmOperatorType *ot)
|
|
||||||
{
|
|
||||||
static const EnumPropertyItem type_items[] = {
|
|
||||||
{PATH_SELECT_EDGE_LENGTH, "EDGE_LENGTH", 0, "Edge Length", NULL},
|
|
||||||
{PATH_SELECT_TOPOLOGICAL, "TOPOLOGICAL", 0, "Topological", NULL},
|
|
||||||
{0, NULL, 0, NULL, NULL}};
|
|
||||||
|
|
||||||
/* identifiers */
|
|
||||||
ot->name= "Select Vertex Path";
|
|
||||||
ot->idname= "MESH_OT_select_vertex_path";
|
|
||||||
|
|
||||||
/* api callbacks */
|
|
||||||
ot->exec= select_vertex_path_exec;
|
|
||||||
ot->invoke= WM_menu_invoke;
|
|
||||||
ot->poll= ED_operator_editmesh;
|
|
||||||
|
|
||||||
/* flags */
|
|
||||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
|
||||||
|
|
||||||
/* properties */
|
|
||||||
RNA_def_enum(ot->srna, "type", type_items, PATH_SELECT_EDGE_LENGTH, "Type", "Method to compute distance.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************** Region/Loop Operators *************************/
|
/********************** Region/Loop Operators *************************/
|
||||||
|
|
||||||
|
@ -281,7 +281,9 @@ void MESH_OT_uvs_rotate(struct wmOperatorType *ot);
|
|||||||
//void MESH_OT_uvs_mirror(struct wmOperatorType *ot);
|
//void MESH_OT_uvs_mirror(struct wmOperatorType *ot);
|
||||||
void MESH_OT_uvs_reverse(struct wmOperatorType *ot);
|
void MESH_OT_uvs_reverse(struct wmOperatorType *ot);
|
||||||
void MESH_OT_colors_rotate(struct wmOperatorType *ot);
|
void MESH_OT_colors_rotate(struct wmOperatorType *ot);
|
||||||
void MESH_OT_colors_mirror(struct wmOperatorType *ot);
|
//void MESH_OT_colors_mirror(struct wmOperatorType *ot);
|
||||||
|
|
||||||
|
void MESH_OT_colors_reverse(struct wmOperatorType *ot);
|
||||||
|
|
||||||
void MESH_OT_delete(struct wmOperatorType *ot);
|
void MESH_OT_delete(struct wmOperatorType *ot);
|
||||||
void MESH_OT_rip(struct wmOperatorType *ot);
|
void MESH_OT_rip(struct wmOperatorType *ot);
|
||||||
|
@ -171,7 +171,8 @@ static int face_specials_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
|||||||
//uiItemMenuEnumO(layout, NULL, 0, "MESH_OT_uvs_mirror", "axis");
|
//uiItemMenuEnumO(layout, NULL, 0, "MESH_OT_uvs_mirror", "axis");
|
||||||
uiItemO(layout, NULL, 0, "MESH_OT_uvs_reverse");
|
uiItemO(layout, NULL, 0, "MESH_OT_uvs_reverse");
|
||||||
uiItemMenuEnumO(layout, NULL, 0, "MESH_OT_colors_rotate", "direction");
|
uiItemMenuEnumO(layout, NULL, 0, "MESH_OT_colors_rotate", "direction");
|
||||||
uiItemMenuEnumO(layout, NULL, 0, "MESH_OT_colors_mirror", "axis");
|
//uiItemMenuEnumO(layout, NULL, 0, "MESH_OT_colors_mirror", "axis");
|
||||||
|
uiItemO(layout, NULL, 0, "MESH_OT_colors_reverse");
|
||||||
|
|
||||||
uiPupMenuEnd(C, pup);
|
uiPupMenuEnd(C, pup);
|
||||||
|
|
||||||
@ -291,7 +292,8 @@ void ED_operatortypes_mesh(void)
|
|||||||
//WM_operatortype_append(MESH_OT_uvs_mirror);
|
//WM_operatortype_append(MESH_OT_uvs_mirror);
|
||||||
WM_operatortype_append(MESH_OT_uvs_reverse);
|
WM_operatortype_append(MESH_OT_uvs_reverse);
|
||||||
WM_operatortype_append(MESH_OT_colors_rotate);
|
WM_operatortype_append(MESH_OT_colors_rotate);
|
||||||
WM_operatortype_append(MESH_OT_colors_mirror);
|
//WM_operatortype_append(MESH_OT_colors_mirror);
|
||||||
|
WM_operatortype_append(MESH_OT_colors_reverse);
|
||||||
|
|
||||||
WM_operatortype_append(MESH_OT_fill);
|
WM_operatortype_append(MESH_OT_fill);
|
||||||
WM_operatortype_append(MESH_OT_beauty_fill);
|
WM_operatortype_append(MESH_OT_beauty_fill);
|
||||||
@ -453,7 +455,8 @@ void ED_keymap_mesh(wmWindowManager *wm)
|
|||||||
//WM_keymap_add_item(keymap, "MESH_OT_uvs_mirror",SEVENKEY, KM_PRESS, KM_ALT, 0);
|
//WM_keymap_add_item(keymap, "MESH_OT_uvs_mirror",SEVENKEY, KM_PRESS, KM_ALT, 0);
|
||||||
WM_keymap_add_item(keymap, "MESH_OT_uvs_reverse",SEVENKEY, KM_PRESS, KM_ALT, 0);
|
WM_keymap_add_item(keymap, "MESH_OT_uvs_reverse",SEVENKEY, KM_PRESS, KM_ALT, 0);
|
||||||
WM_keymap_add_item(keymap, "MESH_OT_colors_rotate",EIGHTKEY, KM_PRESS, KM_CTRL, 0);
|
WM_keymap_add_item(keymap, "MESH_OT_colors_rotate",EIGHTKEY, KM_PRESS, KM_CTRL, 0);
|
||||||
WM_keymap_add_item(keymap, "MESH_OT_colors_mirror",EIGHTKEY, KM_PRESS, KM_ALT, 0);
|
//WM_keymap_add_item(keymap, "MESH_OT_colors_mirror",EIGHTKEY, KM_PRESS, KM_ALT, 0);
|
||||||
|
WM_keymap_add_item(keymap, "MESH_OT_colors_reverse",EIGHTKEY, KM_PRESS, KM_ALT, 0);
|
||||||
|
|
||||||
WM_keymap_add_item(keymap, "MESH_OT_rip_move",VKEY, KM_PRESS, 0, 0);
|
WM_keymap_add_item(keymap, "MESH_OT_rip_move",VKEY, KM_PRESS, 0, 0);
|
||||||
WM_keymap_add_item(keymap, "MESH_OT_merge", MKEY, KM_PRESS, KM_ALT, 0);
|
WM_keymap_add_item(keymap, "MESH_OT_merge", MKEY, KM_PRESS, KM_ALT, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user