finished bmeshafying merge, though probably needs further testing and debugging. also fixed nasty bug in DM_to_mesh.
This commit is contained in:
@@ -406,6 +406,8 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me)
|
||||
totloop += iter->len;
|
||||
}
|
||||
iter->free(iter);
|
||||
|
||||
tmp.totloop = totloop;
|
||||
|
||||
CustomData_copy(&dm->vertData, &tmp.vdata, CD_MASK_MESH, CD_DUPLICATE, totvert);
|
||||
CustomData_copy(&dm->edgeData, &tmp.edata, CD_MASK_MESH, CD_DUPLICATE, totedge);
|
||||
|
||||
@@ -237,6 +237,35 @@ BMOpDefine def_collapse = {
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Facedata point Merge
|
||||
|
||||
Merge uv/vcols at a specific vertex.
|
||||
*/
|
||||
BMOpDefine def_pointmerge_facedata = {
|
||||
"pointmerge_facedata",
|
||||
{{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, /*input vertices*/
|
||||
{BMOP_OPSLOT_ELEMENT_BUF, "snapv"}, /*snap vertex*/
|
||||
{0, /*null-terminating sentinel*/}},
|
||||
bmesh_pointmerge_facedata_exec,
|
||||
0,
|
||||
};
|
||||
|
||||
/*
|
||||
Average Vertices Facevert Data
|
||||
|
||||
Merge uv/vcols associated with the input vertices at
|
||||
the bounding box center. (I know, it's not averaging but
|
||||
the vert_snap_to_bb_center is just too long).
|
||||
*/
|
||||
BMOpDefine def_vert_average_facedata = {
|
||||
"vert_average_facedata",
|
||||
{{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, /*input vertices*/
|
||||
{0, /*null-terminating sentinel*/}},
|
||||
bmesh_vert_average_facedata_exec,
|
||||
0,
|
||||
};
|
||||
|
||||
/*
|
||||
Point Merge
|
||||
|
||||
@@ -704,6 +733,8 @@ BMOpDefine *opdefines[] = {
|
||||
&def_similarfaces,
|
||||
&def_similaredges,
|
||||
&def_similarverts,
|
||||
&def_pointmerge_facedata,
|
||||
&def_vert_average_facedata,
|
||||
};
|
||||
|
||||
int bmesh_total_ops = (sizeof(opdefines) / sizeof(void*));
|
||||
|
||||
@@ -49,4 +49,7 @@ void bmesh_collapse_exec(BMesh *bm, BMOperator *op);
|
||||
void bmesh_similarfaces_exec(BMesh *bm, BMOperator *op);
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -213,17 +213,120 @@ static int vergaverco(const void *e1, const void *e2)
|
||||
|
||||
#define EDGE_MARK 1
|
||||
|
||||
void bmesh_pointmerge_facedata_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
BMOIter siter;
|
||||
BMIter iter;
|
||||
BMVert *v, *snapv;
|
||||
BMLoop *l, *firstl = NULL;
|
||||
float fac;
|
||||
int i, tot;
|
||||
|
||||
snapv = BMO_IterNew(&siter, bm, op, "snapv", BM_VERT);
|
||||
tot = BM_Vert_FaceCount(snapv);
|
||||
|
||||
if (!tot)
|
||||
return;
|
||||
|
||||
fac = 1.0f / tot;
|
||||
BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, snapv) {
|
||||
if (!firstl) {
|
||||
firstl = l;
|
||||
}
|
||||
|
||||
for (i=0; i<bm->ldata.totlayer; i++) {
|
||||
if (CustomData_layer_has_math(&bm->ldata, i)) {
|
||||
int type = bm->ldata.layers[i].type;
|
||||
void *e1, *e2;
|
||||
|
||||
e1 = CustomData_bmesh_get_layer_n(&bm->ldata, firstl->head.data, i);
|
||||
e2 = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
|
||||
|
||||
CustomData_data_multiply(type, e2, fac);
|
||||
|
||||
if (l != firstl)
|
||||
CustomData_data_add(type, e1, e2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
|
||||
BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, v) {
|
||||
if (l == firstl)
|
||||
continue;
|
||||
|
||||
CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, firstl->head.data, &l->head.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bmesh_vert_average_facedata_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
BMOIter siter;
|
||||
BMIter iter;
|
||||
BMVert *v;
|
||||
BMLoop *l, *firstl = NULL;
|
||||
CDBlockBytes min, max;
|
||||
void *block;
|
||||
int i, type;
|
||||
|
||||
for (i=0; i<bm->ldata.totlayer; i++) {
|
||||
if (!CustomData_layer_has_math(&bm->ldata, i))
|
||||
continue;
|
||||
|
||||
type = bm->ldata.layers[i].type;
|
||||
CustomData_data_initminmax(type, &min, &max);
|
||||
|
||||
BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
|
||||
BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, v) {
|
||||
block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
|
||||
CustomData_data_dominmax(type, block, &min, &max);
|
||||
}
|
||||
}
|
||||
|
||||
CustomData_data_multiply(type, &min, 0.5f);
|
||||
CustomData_data_multiply(type, &max, 0.5f);
|
||||
CustomData_data_add(type, &min, &max);
|
||||
|
||||
BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
|
||||
BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, v) {
|
||||
block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
|
||||
CustomData_data_copy_value(type, &min, block);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bmesh_pointmerge_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
BMOperator weldop;
|
||||
BMOIter siter;
|
||||
BMVert *v, *snapv = NULL;
|
||||
float vec[3];
|
||||
|
||||
BMO_Get_Vec(op, "mergeco", vec);
|
||||
|
||||
//BMO_CallOpf(bm, "collapse_uvs edges=%s", op, "edges");
|
||||
BMO_Init_Op(&weldop, "weldverts");
|
||||
|
||||
BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
|
||||
if (!snapv) {
|
||||
snapv = v;
|
||||
VECCOPY(snapv->co, vec);
|
||||
} else {
|
||||
BMO_Insert_MapPointer(bm, &weldop, "targetmap", v, snapv);
|
||||
}
|
||||
}
|
||||
|
||||
BMO_Exec_Op(bm, &weldop);
|
||||
BMO_Finish_Op(bm, &weldop);
|
||||
}
|
||||
|
||||
void bmesh_collapse_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
BMOperator weldop;
|
||||
BMWalker walker;
|
||||
BMOIter siter;
|
||||
BMIter iter, liter, liter2;
|
||||
BMVert *v;
|
||||
BMIter iter;
|
||||
BMEdge *e, **edges = NULL;
|
||||
V_DECLARE(edges);
|
||||
float min[3], max[3];
|
||||
@@ -276,11 +379,9 @@ void bmesh_collapse_exec(BMesh *bm, BMOperator *op)
|
||||
/*uv collapse function*/
|
||||
void bmesh_collapsecon_do_layer(BMesh *bm, BMOperator *op, int layer)
|
||||
{
|
||||
BMIter iter, liter, liter2;
|
||||
BMIter iter, liter;
|
||||
BMFace *f;
|
||||
BMLoop *l, *l2;
|
||||
BMEdge *e;
|
||||
BMVert *v;
|
||||
BMWalker walker;
|
||||
void **blocks = NULL;
|
||||
V_DECLARE(blocks);
|
||||
|
||||
@@ -1632,7 +1632,6 @@ static int edge_rotate_selected(bContext *C, wmOperator *op)
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
|
||||
BMOperator bmop;
|
||||
BMOIter siter;
|
||||
BMEdge *eed;
|
||||
BMIter iter;
|
||||
int ccw = RNA_int_get(op->ptr, "direction") == 1; // direction == 2 when clockwise and ==1 for counter CW.
|
||||
@@ -2423,3 +2422,179 @@ void MESH_OT_colors_mirror(wmOperatorType *ot)
|
||||
/* props */
|
||||
RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around.");
|
||||
}
|
||||
|
||||
|
||||
static int merge_firstlast(BMEditMesh *em, int first, int uvmerge, wmOperator *wmop)
|
||||
{
|
||||
BMVert *mergevert;
|
||||
BMEditSelection *ese;
|
||||
|
||||
/* do sanity check in mergemenu in edit.c ?*/
|
||||
if(first == 0){
|
||||
ese = em->bm->selected.last;
|
||||
mergevert= (BMVert*)ese->data;
|
||||
}
|
||||
else{
|
||||
ese = em->bm->selected.first;
|
||||
mergevert = (BMVert*)ese->data;
|
||||
}
|
||||
|
||||
if (!BM_TestHFlag(mergevert, BM_SELECT))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
if (uvmerge) {
|
||||
if (!EDBM_CallOpf(em, wmop, "pointmerge_facedata verts=%hv snapv=%e", BM_SELECT, mergevert))
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (!EDBM_CallOpf(em, wmop, "pointmerge verts=%hv mergeco=%v", BM_SELECT, mergevert->co))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int merge_target(BMEditMesh *em, Scene *scene, View3D *v3d,
|
||||
int target, int uvmerge, wmOperator *wmop)
|
||||
{
|
||||
BMIter iter;
|
||||
BMVert *v;
|
||||
float *co, cent[3] = {0.0f, 0.0f, 0.0f}, fac;
|
||||
int i;
|
||||
|
||||
if (target) {
|
||||
co = give_cursor(scene, v3d);
|
||||
} else {
|
||||
i = 0;
|
||||
BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
|
||||
if (!BM_TestHFlag(v, BM_SELECT))
|
||||
continue;
|
||||
VECADD(cent, cent, v->co);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (!i)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
fac = 1.0f / (float)i;
|
||||
VECMUL(cent, fac);
|
||||
co = cent;
|
||||
}
|
||||
|
||||
if (!co)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
if (uvmerge) {
|
||||
if (!EDBM_CallOpf(em, wmop, "vert_average_facedata verts=%hv", BM_SELECT))
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (!EDBM_CallOpf(em, wmop, "pointmerge verts=%hv mergeco=%v", BM_SELECT, co))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int merge_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
|
||||
int status= 0, uvs= RNA_boolean_get(op->ptr, "uvs");
|
||||
|
||||
switch(RNA_enum_get(op->ptr, "type")) {
|
||||
case 3:
|
||||
status = merge_target(em, scene, v3d, 0, uvs, op);
|
||||
break;
|
||||
case 4:
|
||||
status = merge_target(em, scene, v3d, 1, uvs, op);
|
||||
break;
|
||||
case 1:
|
||||
status = merge_firstlast(em, 0, uvs, op);
|
||||
break;
|
||||
case 6:
|
||||
status = merge_firstlast(em, 1, uvs, op);
|
||||
break;
|
||||
case 5:
|
||||
status = 1;
|
||||
if (!EDBM_CallOpf(em, op, "collapse edges=%he", BM_SELECT))
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!status)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static EnumPropertyItem merge_type_items[]= {
|
||||
{6, "FIRST", 0, "At First", ""},
|
||||
{1, "LAST", 0, "At Last", ""},
|
||||
{3, "CENTER", 0, "At Center", ""},
|
||||
{4, "CURSOR", 0, "At Cursor", ""},
|
||||
{5, "COLLAPSE", 0, "Collapse", ""},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *ptr, int *free)
|
||||
{
|
||||
Object *obedit;
|
||||
EnumPropertyItem *item= NULL;
|
||||
int totitem= 0;
|
||||
|
||||
if(!C) /* needed for docs */
|
||||
return merge_type_items;
|
||||
|
||||
obedit= CTX_data_edit_object(C);
|
||||
if(obedit && obedit->type == OB_MESH) {
|
||||
BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
|
||||
|
||||
if(em->selectmode & SCE_SELECT_VERTEX) {
|
||||
if(em->bm->selected.first && em->bm->selected.last &&
|
||||
((BMEditSelection*)em->bm->selected.first)->type == BM_VERT && ((BMEditSelection*)em->bm->selected.last)->type == BM_VERT) {
|
||||
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
|
||||
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
|
||||
}
|
||||
else if(em->bm->selected.first && ((BMEditSelection*)em->bm->selected.first)->type == BM_VERT)
|
||||
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
|
||||
else if(em->bm->selected.last && ((BMEditSelection*)em->bm->selected.last)->type == BM_VERT)
|
||||
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
|
||||
}
|
||||
|
||||
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 3);
|
||||
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 4);
|
||||
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 5);
|
||||
RNA_enum_item_end(&item, &totitem);
|
||||
|
||||
*free= 1;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MESH_OT_merge(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* identifiers */
|
||||
ot->name= "Merge";
|
||||
ot->idname= "MESH_OT_merge";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= merge_exec;
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->poll= ED_operator_editmesh;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
prop= RNA_def_enum(ot->srna, "type", merge_type_items, 3, "Type", "Merge method to use.");
|
||||
RNA_def_enum_funcs(prop, merge_type_itemf);
|
||||
RNA_def_boolean(ot->srna, "uvs", 0, "UVs", "Move UVs according to merge.");
|
||||
}
|
||||
|
||||
@@ -5417,164 +5417,6 @@ int collapseEdges(EditMesh *em)
|
||||
return mergecount;
|
||||
}
|
||||
|
||||
int merge_firstlast(EditMesh *em, int first, int uvmerge)
|
||||
{
|
||||
EditVert *eve,*mergevert;
|
||||
EditSelection *ese;
|
||||
|
||||
/* do sanity check in mergemenu in edit.c ?*/
|
||||
if(first == 0){
|
||||
ese = em->selected.last;
|
||||
mergevert= (EditVert*)ese->data;
|
||||
}
|
||||
else{
|
||||
ese = em->selected.first;
|
||||
mergevert = (EditVert*)ese->data;
|
||||
}
|
||||
|
||||
if(mergevert->f&SELECT){
|
||||
for (eve=em->verts.first; eve; eve=eve->next){
|
||||
if (eve->f&SELECT)
|
||||
VECCOPY(eve->co,mergevert->co);
|
||||
}
|
||||
}
|
||||
|
||||
if(uvmerge && CustomData_has_layer(&em->fdata, CD_MTFACE)){
|
||||
|
||||
for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0;
|
||||
for(eve=em->verts.first; eve; eve=eve->next){
|
||||
if(eve->f&SELECT) eve->f1 = 1;
|
||||
}
|
||||
collapseuvs(em, mergevert);
|
||||
}
|
||||
|
||||
return removedoublesflag(em, 1, 0, MERGELIMIT);
|
||||
}
|
||||
|
||||
int merge_target(EditMesh *em, int target, int uvmerge)
|
||||
{
|
||||
EditVert *eve;
|
||||
|
||||
// XXX not working
|
||||
if(target) snap_sel_to_curs();
|
||||
else snap_to_center();
|
||||
|
||||
if(uvmerge && CustomData_has_layer(&em->fdata, CD_MTFACE)){
|
||||
for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0;
|
||||
for(eve=em->verts.first; eve; eve=eve->next){
|
||||
if(eve->f&SELECT) eve->f1 = 1;
|
||||
}
|
||||
collapseuvs(em, NULL);
|
||||
}
|
||||
|
||||
return removedoublesflag(em, 1, 0, MERGELIMIT);
|
||||
}
|
||||
#undef MERGELIMIT
|
||||
|
||||
static int merge_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
|
||||
int count= 0, uvs= RNA_boolean_get(op->ptr, "uvs");
|
||||
|
||||
switch(RNA_enum_get(op->ptr, "type")) {
|
||||
case 3:
|
||||
count = merge_target(em, 0, uvs);
|
||||
break;
|
||||
case 4:
|
||||
count = merge_target(em, 1, uvs);
|
||||
break;
|
||||
case 1:
|
||||
count = merge_firstlast(em, 0, uvs);
|
||||
break;
|
||||
case 6:
|
||||
count = merge_firstlast(em, 1, uvs);
|
||||
break;
|
||||
case 2:
|
||||
count = collapseEdges(em);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!count)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
BKE_mesh_end_editmesh(obedit->data, em);
|
||||
|
||||
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static EnumPropertyItem merge_type_items[]= {
|
||||
{6, "FIRST", 0, "At First", ""},
|
||||
{1, "LAST", 0, "At Last", ""},
|
||||
{3, "CENTER", 0, "At Center", ""},
|
||||
{4, "CURSOR", 0, "At Cursor", ""},
|
||||
{5, "COLLAPSE", 0, "Collapse", ""},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *ptr, int *free)
|
||||
{
|
||||
Object *obedit;
|
||||
EnumPropertyItem *item= NULL;
|
||||
int totitem= 0;
|
||||
|
||||
if(!C) /* needed for docs */
|
||||
return merge_type_items;
|
||||
|
||||
obedit= CTX_data_edit_object(C);
|
||||
if(obedit && obedit->type == OB_MESH) {
|
||||
EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
|
||||
|
||||
if(em->selectmode & SCE_SELECT_VERTEX) {
|
||||
if(em->selected.first && em->selected.last &&
|
||||
((EditSelection*)em->selected.first)->type == EDITVERT && ((EditSelection*)em->selected.last)->type == EDITVERT) {
|
||||
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
|
||||
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
|
||||
}
|
||||
else if(em->selected.first && ((EditSelection*)em->selected.first)->type == EDITVERT)
|
||||
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
|
||||
else if(em->selected.last && ((EditSelection*)em->selected.last)->type == EDITVERT)
|
||||
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
|
||||
}
|
||||
|
||||
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 3);
|
||||
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 4);
|
||||
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 5);
|
||||
RNA_enum_item_end(&item, &totitem);
|
||||
|
||||
*free= 1;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MESH_OT_merge(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* identifiers */
|
||||
ot->name= "Merge";
|
||||
ot->idname= "MESH_OT_merge";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= merge_exec;
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->poll= ED_operator_editmesh;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
prop= RNA_def_enum(ot->srna, "type", merge_type_items, 3, "Type", "Merge method to use.");
|
||||
RNA_def_enum_funcs(prop, merge_type_itemf);
|
||||
RNA_def_boolean(ot->srna, "uvs", 0, "UVs", "Move UVs according to merge.");
|
||||
}
|
||||
|
||||
/************************ Vertex Path Operator *************************/
|
||||
|
||||
typedef struct PathNode {
|
||||
|
||||
Reference in New Issue
Block a user