Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert extrude already did). Note that I need to port this, after we all figure out how to handle operators with variable transform follow-ons. I also implemented the merge->collapse function, which is currently accessable under ctrl->v, Bmesh Test Operator. I still need to implement the other merge modes, and properly hook everything into the merge menu tool, which I plan on doing soon (tomorrow hopefully). The cool thing about the collapse tool, is not only does it handle (all) UV layers, it handles vcols as well. To do this, I had to add a few math functions to the customdata API, which seem to be working well.
This commit is contained in:
@@ -37,6 +37,9 @@ struct CustomData;
|
||||
struct CustomDataLayer;
|
||||
typedef unsigned int CustomDataMask;
|
||||
|
||||
/*a data type large enough to hold 1 element from any customdata layer type*/
|
||||
typedef struct {unsigned char data[64];} CDBlockBytes;
|
||||
|
||||
extern const CustomDataMask CD_MASK_BAREMESH;
|
||||
extern const CustomDataMask CD_MASK_MESH;
|
||||
extern const CustomDataMask CD_MASK_EDITMESH;
|
||||
@@ -59,6 +62,20 @@ extern const CustomDataMask CD_MASK_FACECORNERS;
|
||||
#define CD_DUPLICATE 4 /* do a full copy of all layers, only allowed if source
|
||||
has same number of elements */
|
||||
|
||||
/* Checks if the layer at physical offset layern (in data->layers) support math
|
||||
* the below operations.
|
||||
*/
|
||||
int CustomData_layer_has_math(struct CustomData *data, int layern);
|
||||
|
||||
/* compares if data1 is equal to data2. type is a valid CustomData type
|
||||
* enum (e.g. CD_MLOOPUV). the layer type's equal function is used to compare
|
||||
* the data, if it exists, otherwise memcmp is used.*/
|
||||
int CustomData_data_equals(int type, void *data1, void *data2);
|
||||
void CustomData_data_initminmax(int type, void *min, void *max);
|
||||
void CustomData_data_dominmax(int type, void *data, void *min, void *max);
|
||||
void CustomData_data_multiply(int type, void *data, float fac);
|
||||
void CustomData_data_add(int type, void *data1, void *data2);
|
||||
|
||||
/* initialises a CustomData object with the same layer setup as source.
|
||||
* mask is a bitfield where (mask & (1 << (layer type))) indicates
|
||||
* if a layer should be copied or not. alloctype must be one of the above. */
|
||||
@@ -192,6 +209,10 @@ void *CustomData_em_get_n(const struct CustomData *data, void *block, int type,
|
||||
void *CustomData_bmesh_get(const struct CustomData *data, void *block, int type);
|
||||
void *CustomData_bmesh_get_n(const struct CustomData *data, void *block, int type, int n);
|
||||
|
||||
/* gets the layer at physical index n, with no type checking.
|
||||
*/
|
||||
void *CustomData_bmesh_get_layer_n(const struct CustomData *data, void *block, int n);
|
||||
|
||||
/* gets a pointer to the active or first layer of type
|
||||
* returns NULL if there is no layer of type
|
||||
*/
|
||||
@@ -227,6 +248,11 @@ void CustomData_bmesh_set(const struct CustomData *data, void *block, int type,
|
||||
|
||||
void CustomData_bmesh_set_n(struct CustomData *data, void *block, int type, int n,
|
||||
void *source);
|
||||
/*sets the data of the block at physical layer n. no real type checking
|
||||
*is performed.
|
||||
*/
|
||||
void CustomData_bmesh_set_layer_n(struct CustomData *data, void *block, int n,
|
||||
void *source);
|
||||
|
||||
/* set the pointer of to the first layer of type. the old data is not freed.
|
||||
* returns the value of ptr if the layer is found, NULL otherwise
|
||||
|
||||
@@ -91,6 +91,13 @@ typedef struct LayerTypeInfo {
|
||||
/* a function to set a layer's data to default values. if NULL, the
|
||||
default is assumed to be all zeros */
|
||||
void (*set_default)(void *data, int count);
|
||||
|
||||
/* functions necassary for geometry collapse*/
|
||||
int (*equal)(void *data1, void *data2);
|
||||
void (*multiply)(void *data, float fac);
|
||||
void (*initminmax)(void *min, void *max);
|
||||
void (*add)(void *data1, void *data2);
|
||||
void (*dominmax)(void *data1, void *min, void *max);
|
||||
} LayerTypeInfo;
|
||||
|
||||
static void layerCopy_mdeformvert(const void *source, void *dest,
|
||||
@@ -535,11 +542,76 @@ static void layerFree_mdisps(void *data, int count, int size)
|
||||
|
||||
/* --------- */
|
||||
|
||||
static int layerEqual_mloopcol(void *data1, void *data2)
|
||||
{
|
||||
MLoopCol *m1 = data1, *m2 = data2;
|
||||
float r, g, b, a;
|
||||
|
||||
r = m1->r - m2->r;
|
||||
g = m1->g - m2->g;
|
||||
b = m1->b - m2->b;
|
||||
a = m1->a - m2->a;
|
||||
|
||||
return r*r + g*g + b*b + a*a < 0.001;
|
||||
}
|
||||
|
||||
static void layerMultiply_mloopcol(void *data, float fac)
|
||||
{
|
||||
MLoopCol *m = data;
|
||||
|
||||
m->r = (float)m->r * fac;
|
||||
m->g = (float)m->g * fac;
|
||||
m->b = (float)m->b * fac;
|
||||
m->a = (float)m->a * fac;
|
||||
}
|
||||
|
||||
static void layerAdd_mloopcol(void *data1, void *data2)
|
||||
{
|
||||
MLoopCol *m = data1, *m2 = data2;
|
||||
|
||||
m->r += m2->r;
|
||||
m->g += m2->g;
|
||||
m->b += m2->b;
|
||||
m->a += m2->a;
|
||||
}
|
||||
|
||||
static void layerDoMinMax_mloopcol(void *data, void *vmin, void *vmax)
|
||||
{
|
||||
MLoopCol *m = data;
|
||||
MLoopCol *min = vmin, *max = vmax;
|
||||
|
||||
if (m->r < min->r) min->r = m->r;
|
||||
if (m->g < min->g) min->g = m->g;
|
||||
if (m->b < min->b) min->b = m->b;
|
||||
if (m->a < min->a) min->a = m->a;
|
||||
|
||||
if (m->r > max->r) max->r = m->r;
|
||||
if (m->g > max->g) max->g = m->g;
|
||||
if (m->b > max->b) max->b = m->b;
|
||||
if (m->a > max->a) max->a = m->a;
|
||||
}
|
||||
|
||||
static void layerInitMinMax_mloopcol(void *vmin, void *vmax)
|
||||
{
|
||||
MLoopCol *min = vmin, *max = vmax;
|
||||
|
||||
min->r = 255;
|
||||
min->g = 255;
|
||||
min->b = 255;
|
||||
min->a = 255;
|
||||
|
||||
max->r = 0;
|
||||
max->g = 0;
|
||||
max->b = 0;
|
||||
max->a = 0;
|
||||
}
|
||||
|
||||
static void layerDefault_mloopcol(void *data, int count)
|
||||
{
|
||||
static MLoopCol default_mloopcol = {255,255,255,255};
|
||||
MLoopCol default_mloopcol = {255,255,255,255};
|
||||
MLoopCol *mlcol = (MLoopCol*)data;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < count; i++)
|
||||
mlcol[i] = default_mloopcol;
|
||||
|
||||
@@ -589,6 +661,48 @@ static void layerInterp_mloopcol(void **sources, float *weights,
|
||||
mc->g = (int)col.g;
|
||||
mc->b = (int)col.b;
|
||||
}
|
||||
|
||||
static int layerEqual_mloopuv(void *data1, void *data2)
|
||||
{
|
||||
MLoopUV *luv1 = data1, *luv2 = data2;
|
||||
float u, v;
|
||||
|
||||
u = luv1->uv[0] - luv2->uv[0];
|
||||
v = luv1->uv[1] - luv2->uv[1];
|
||||
|
||||
return u*u + v*v < 0.00001;
|
||||
}
|
||||
|
||||
static void layerMultiply_mloopuv(void *data, float fac)
|
||||
{
|
||||
MLoopUV *luv = data;
|
||||
|
||||
luv->uv[0] *= fac;
|
||||
luv->uv[1] *= fac;
|
||||
}
|
||||
|
||||
static void layerInitMinMax_mloopuv(void *vmin, void *vmax)
|
||||
{
|
||||
MLoopUV *min = vmin, *max = vmax;
|
||||
|
||||
INIT_MINMAX2(min->uv, max->uv);
|
||||
}
|
||||
|
||||
static void layerDoMinMax_mloopuv(void *data, void *vmin, void *vmax)
|
||||
{
|
||||
MLoopUV *min = vmin, *max = vmax, *luv = data;
|
||||
|
||||
DO_MINMAX2(luv->uv, min->uv, max->uv);
|
||||
}
|
||||
|
||||
static void layerAdd_mloopuv(void *data1, void *data2)
|
||||
{
|
||||
MLoopUV *l1 = data1, *l2 = data2;
|
||||
|
||||
l1->uv[0] += l2->uv[0];
|
||||
l1->uv[1] += l2->uv[1];
|
||||
}
|
||||
|
||||
static void layerInterp_mloopuv(void **sources, float *weights,
|
||||
float *sub_weights, int count, void *dest)
|
||||
{
|
||||
@@ -722,8 +836,12 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
||||
layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face},
|
||||
{sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
|
||||
{sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL},
|
||||
{sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL},
|
||||
{sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol},
|
||||
{sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL,
|
||||
layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv,
|
||||
layerAdd_mloopuv, layerDoMinMax_mloopuv},
|
||||
{sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL,
|
||||
layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol,
|
||||
layerAdd_mloopcol, layerDoMinMax_mloopcol},
|
||||
{sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
|
||||
{sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps,
|
||||
layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL},
|
||||
@@ -1872,7 +1990,7 @@ void CustomData_bmesh_merge(CustomData *source, CustomData *dest,
|
||||
BMIter iter;
|
||||
CustomData destold = *dest;
|
||||
void *tmp;
|
||||
int i, t;
|
||||
int t;
|
||||
|
||||
CustomData_merge(source, dest, mask, alloctype, 0);
|
||||
CustomData_bmesh_init_pool(dest, 512);
|
||||
@@ -2014,6 +2132,68 @@ void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int
|
||||
return (char *)block + data->layers[layer_index+n].offset;
|
||||
}
|
||||
|
||||
/*gets from the layer at physical index n, note: doesn't check type.*/
|
||||
void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n)
|
||||
{
|
||||
if(n < 0 || n >= data->totlayer) return NULL;
|
||||
|
||||
return (char *)block + data->layers[n].offset;
|
||||
}
|
||||
|
||||
int CustomData_layer_has_math(struct CustomData *data, int layern)
|
||||
{
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[layern].type);
|
||||
|
||||
if (typeInfo->equal && typeInfo->add && typeInfo->multiply &&
|
||||
typeInfo->initminmax && typeInfo->dominmax) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CustomData_data_equals(int type, void *data1, void *data2)
|
||||
{
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
||||
|
||||
if (typeInfo->equal)
|
||||
return typeInfo->equal(data1, data2);
|
||||
else return !memcmp(data1, data2, typeInfo->size);
|
||||
}
|
||||
|
||||
void CustomData_data_initminmax(int type, void *min, void *max)
|
||||
{
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
||||
|
||||
if (typeInfo->equal)
|
||||
typeInfo->initminmax(min, max);
|
||||
}
|
||||
|
||||
|
||||
void CustomData_data_dominmax(int type, void *data, void *min, void *max)
|
||||
{
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
||||
|
||||
if (typeInfo->equal)
|
||||
typeInfo->dominmax(data, min, max);
|
||||
}
|
||||
|
||||
|
||||
void CustomData_data_multiply(int type, void *data, float fac)
|
||||
{
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
||||
|
||||
if (typeInfo->equal)
|
||||
typeInfo->multiply(data, fac);
|
||||
}
|
||||
|
||||
|
||||
void CustomData_data_add(int type, void *data1, void *data2)
|
||||
{
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
||||
|
||||
if (typeInfo->equal)
|
||||
typeInfo->add(data1, data2);
|
||||
}
|
||||
|
||||
void CustomData_bmesh_set(const CustomData *data, void *block, int type, void *source)
|
||||
{
|
||||
void *dest = CustomData_bmesh_get(data, block, type);
|
||||
@@ -2040,6 +2220,19 @@ void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, void
|
||||
memcpy(dest, source, typeInfo->size);
|
||||
}
|
||||
|
||||
void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, void *source)
|
||||
{
|
||||
void *dest = CustomData_bmesh_get_layer_n(data, block, n);
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type);
|
||||
|
||||
if(!dest) return;
|
||||
|
||||
if(typeInfo->copy)
|
||||
typeInfo->copy(source, dest, 1);
|
||||
else
|
||||
memcpy(dest, source, typeInfo->size);
|
||||
}
|
||||
|
||||
void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights,
|
||||
float *sub_weights, int count, void *dest_block)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,21 @@
|
||||
#define BM_EDGES_OF_MESH 2
|
||||
#define BM_FACES_OF_MESH 3
|
||||
|
||||
/*these are topological iterators.*/
|
||||
#define BM_EDGES_OF_VERT 4
|
||||
#define BM_FACES_OF_VERT 5
|
||||
#define BM_LOOPS_OF_VERT 6
|
||||
#define BM_FACES_OF_EDGE 7
|
||||
#define BM_VERTS_OF_FACE 8
|
||||
#define BM_FACEVERTS_OF_FACE 9
|
||||
#define BM_EDGES_OF_FACE 10
|
||||
#define BM_LOOPS_OF_FACE 11
|
||||
|
||||
/*iterate through loops around this loop, which are fetched
|
||||
from the other faces in the radial cycle surrounding the
|
||||
input loop's edge.*/
|
||||
#define BM_LOOPS_OF_LOOP 12
|
||||
|
||||
#define BM_ITER(ele, iter, bm, type, data) \
|
||||
ele = BMIter_New(iter, bm, type, data); \
|
||||
for ( ; ele; ele=BMIter_Step(iter))
|
||||
@@ -38,20 +53,6 @@ for (ele = BMIter_New(iter, bm, type, data); ele; ele=BMIter_Step(iter)) {\
|
||||
for (ele = BMIter_New(iter, bm, type, data); ele; ele=BMIter_Step(iter)) {\
|
||||
if (BM_TestHFlag(ele, BM_HIDDEN) || BM_TestHFlag(ele, BM_SELECT)) continue;
|
||||
|
||||
/*these are topological iterators.*/
|
||||
#define BM_EDGES_OF_VERT 4
|
||||
#define BM_FACES_OF_VERT 5
|
||||
#define BM_FACES_OF_EDGE 6
|
||||
#define BM_VERTS_OF_FACE 7
|
||||
#define BM_FACEVERTS_OF_FACE 8
|
||||
#define BM_EDGES_OF_FACE 9
|
||||
#define BM_LOOPS_OF_FACE 10
|
||||
|
||||
/*iterate through loops around this loop, which are fetched
|
||||
from the other faces in the radial cycle surrounding the
|
||||
input loop's edge.*/
|
||||
#define BM_LOOPS_OF_LOOP 11
|
||||
|
||||
|
||||
/*Iterator Structure*/
|
||||
typedef struct BMIter{
|
||||
|
||||
@@ -224,14 +224,14 @@ void BMO_Get_Mat3(struct BMOperator *op, char *slotname, float mat[3][3]);
|
||||
void BMO_Flag_To_Slot(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag, int type);
|
||||
|
||||
/*tool-flags all elements inside an element slot array with flag flag.*/
|
||||
void BMO_Flag_Buffer(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag);
|
||||
void BMO_Flag_Buffer(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag, int type);
|
||||
/*clears tool-flag flag from all elements inside a slot array.*/
|
||||
void BMO_Unflag_Buffer(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag);
|
||||
void BMO_Unflag_Buffer(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag, int type);
|
||||
|
||||
/*tool-flags all elements inside an element slot array with flag flag.*/
|
||||
void BMO_HeaderFlag_Buffer(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag);
|
||||
void BMO_HeaderFlag_Buffer(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag, int type);
|
||||
/*clears tool-flag flag from all elements inside a slot array.*/
|
||||
void BMO_UnHeaderFlag_Buffer(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag);
|
||||
void BMO_UnHeaderFlag_Buffer(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag, int type);
|
||||
|
||||
/*puts every element of type type (which is a bitmask) with header flag
|
||||
flag, into a slot. note: ignores hidden elements (e.g. elements with
|
||||
|
||||
@@ -17,11 +17,12 @@ typedef struct BMWalker {
|
||||
void *(*step) (struct BMWalker *walker);
|
||||
int restrictflag;
|
||||
GHash *visithash;
|
||||
int flag;
|
||||
} BMWalker;
|
||||
|
||||
/*initialize a walker. searchmask restricts some (not all) walkers to
|
||||
elements with a specific tool flag set.*/
|
||||
void BMW_Init(struct BMWalker *walker, BMesh *bm, int type, int searchmask);
|
||||
elements with a specific tool flag set. flags is specific to each walker.*/
|
||||
void BMW_Init(struct BMWalker *walker, BMesh *bm, int type, int searchmask, int flags);
|
||||
void *BMW_Begin(BMWalker *walker, void *start);
|
||||
void *BMW_Step(struct BMWalker *walker);
|
||||
void BMW_End(struct BMWalker *walker);
|
||||
@@ -42,14 +43,22 @@ BMW_End(&walker);
|
||||
|
||||
enum {
|
||||
/*walk over connected geometry. can restrict to a search flag,
|
||||
or not, it's optional.*/
|
||||
or not, it's optional.
|
||||
|
||||
takes a vert as an arugment, and spits out edges, restrict flag acts
|
||||
on the edges as well.*/
|
||||
BMW_SHELL,
|
||||
/*walk over an edge loop. search flag doesn't do anything.*/
|
||||
BMW_LOOP,
|
||||
BMW_FACELOOP,
|
||||
BMW_EDGERING,
|
||||
/*#define BMW_RING 2
|
||||
#define BMW_UVISLANDS 3*/
|
||||
/*#define BMW_RING 2*/
|
||||
//walk over uv islands; takes a loop as input. restrict flag
|
||||
//restricts the walking to loops whose vert has restrict flag set as a
|
||||
//tool flag.
|
||||
//
|
||||
//the flag parameter to BMW_Init maps to a loop customdata layer index.
|
||||
BMW_UVISLAND,
|
||||
/*walk over an island of flagged faces. note, that this doesn't work on
|
||||
non-manifold geometry. it might be better to rewrite this to extract
|
||||
boundary info from the island walker, rather then directly walking
|
||||
|
||||
@@ -69,6 +69,22 @@ void BM_Data_Interp_From_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, flo
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
BM Data Vert Average
|
||||
|
||||
Sets all the customdata (e.g. vert, loop) associated with a vert
|
||||
to the average of the face regions surrounding it.
|
||||
*/
|
||||
|
||||
//CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, vloop->head.data);
|
||||
|
||||
void BM_Data_Vert_Average(BMesh *bm, BMFace *f)
|
||||
{
|
||||
BMIter iter;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* bmesh_data_facevert_edgeinterp
|
||||
*
|
||||
|
||||
@@ -203,6 +203,46 @@ static void *face_of_vert_step(BMIter *iter)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* LOOP OF VERT CALLBACKS
|
||||
*
|
||||
*/
|
||||
|
||||
static void loop_of_vert_begin(BMIter *iter)
|
||||
{
|
||||
init_iterator(iter);
|
||||
iter->count = 0;
|
||||
if(iter->vdata->edge)
|
||||
iter->count = bmesh_disk_count_facevert(iter->vdata);
|
||||
if(iter->count){
|
||||
iter->firstedge = bmesh_disk_find_first_faceedge(iter->vdata->edge, iter->vdata);
|
||||
iter->nextedge = iter->firstedge;
|
||||
iter->firstloop = bmesh_radial_find_first_facevert(iter->firstedge->loop, iter->vdata);
|
||||
iter->nextloop = iter->firstloop;
|
||||
}
|
||||
}
|
||||
static void *loop_of_vert_step(BMIter *iter)
|
||||
{
|
||||
BMLoop *current = iter->nextloop;
|
||||
|
||||
if(iter->count){
|
||||
iter->count--;
|
||||
iter->nextloop = bmesh_radial_find_next_facevert(iter->nextloop, iter->vdata);
|
||||
if(iter->nextloop == iter->firstloop){
|
||||
iter->nextedge = bmesh_disk_find_next_faceedge(iter->nextedge, iter->vdata);
|
||||
iter->firstloop = bmesh_radial_find_first_facevert(iter->nextedge->loop, iter->vdata);
|
||||
iter->nextloop = iter->firstloop;
|
||||
}
|
||||
}
|
||||
|
||||
if(!iter->count) iter->nextloop = NULL;
|
||||
|
||||
|
||||
if(current) return current;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void loops_of_loop_begin(BMIter *iter)
|
||||
{
|
||||
BMLoop *l;
|
||||
@@ -359,6 +399,11 @@ void *BMIter_New(BMIter *iter, BMesh *bm, int type, void *data)
|
||||
iter->step = face_of_vert_step;
|
||||
iter->vdata = data;
|
||||
break;
|
||||
case BM_LOOPS_OF_VERT:
|
||||
iter->begin = loop_of_vert_begin;
|
||||
iter->step = loop_of_vert_step;
|
||||
iter->vdata = data;
|
||||
break;
|
||||
case BM_FACES_OF_EDGE:
|
||||
iter->begin = face_of_edge_begin;
|
||||
iter->step = face_of_edge_step;
|
||||
|
||||
@@ -223,6 +223,47 @@ BMOpDefine def_removedoubles = {
|
||||
0,
|
||||
};
|
||||
|
||||
/*
|
||||
Collapse Connected
|
||||
|
||||
Collapses connected vertices
|
||||
*/
|
||||
BMOpDefine def_collapse = {
|
||||
"collapse",
|
||||
{{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, /*input edges*/
|
||||
{0, /*null-terminating sentinel*/}},
|
||||
bmesh_collapse_exec,
|
||||
0,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Point Merge
|
||||
|
||||
Merge verts together at a point.
|
||||
*/
|
||||
BMOpDefine def_pointmerge = {
|
||||
"pointmerge",
|
||||
{{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, /*input vertices*/
|
||||
{BMOP_OPSLOT_VEC, "mergeco"},
|
||||
{0, /*null-terminating sentinel*/}},
|
||||
bmesh_pointmerge_exec,
|
||||
0,
|
||||
};
|
||||
|
||||
/*
|
||||
Collapse Connected UVs
|
||||
|
||||
Collapses connected UV vertices.
|
||||
*/
|
||||
BMOpDefine def_collapse_uvs = {
|
||||
"collapse_uvs",
|
||||
{{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, /*input edges*/
|
||||
{0, /*null-terminating sentinel*/}},
|
||||
bmesh_collapsecon_exec,
|
||||
0,
|
||||
};
|
||||
|
||||
/*
|
||||
Weld Verts
|
||||
|
||||
@@ -359,6 +400,36 @@ BMOpDefine def_mesh_to_bmesh = {
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
Individual Face Extrude
|
||||
|
||||
Extrudes faces individually.
|
||||
*/
|
||||
BMOpDefine def_extrude_indivface = {
|
||||
"extrude_face_indiv",
|
||||
{{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, //input faces
|
||||
{BMOP_OPSLOT_ELEMENT_BUF, "faceout"}, //output faces
|
||||
{BMOP_OPSLOT_ELEMENT_BUF, "skirtout"}, //output skirt geometry, faces and edges
|
||||
{0} /*null-terminating sentinel*/},
|
||||
bmesh_extrude_face_indiv_exec,
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
Extrude Only Edges
|
||||
|
||||
Extrudes Edges into faces, note that this is very simple, there's no fancy
|
||||
winged extrusion.
|
||||
*/
|
||||
BMOpDefine def_extrude_onlyedge = {
|
||||
"extrude_edge_only",
|
||||
{{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, //input vertices
|
||||
{BMOP_OPSLOT_ELEMENT_BUF, "geomout"}, //output geometry
|
||||
{0} /*null-terminating sentinel*/},
|
||||
bmesh_extrude_onlyedge_exec,
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
Individual Vertex Extrude
|
||||
|
||||
@@ -572,6 +643,11 @@ BMOpDefine *opdefines[] = {
|
||||
&def_regionextend,
|
||||
&def_righthandfaces,
|
||||
&def_vertexsmooth,
|
||||
&def_extrude_onlyedge,
|
||||
&def_extrude_indivface,
|
||||
&def_collapse_uvs,
|
||||
&def_pointmerge,
|
||||
&def_collapse,
|
||||
};
|
||||
|
||||
int bmesh_total_ops = (sizeof(opdefines) / sizeof(void*));
|
||||
|
||||
@@ -739,16 +739,19 @@ void BMO_Flag_To_Slot(BMesh *bm, BMOperator *op, char *slotname, int flag, int t
|
||||
*
|
||||
*/
|
||||
|
||||
void BMO_HeaderFlag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag)
|
||||
void BMO_HeaderFlag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag, int type)
|
||||
{
|
||||
BMOpSlot *slot = BMO_GetSlot(op, slotname);
|
||||
BMHeader **data = slot->data.p;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < slot->len; i++) {
|
||||
BM_SetHFlag(data[i], flag);
|
||||
if (!(type & data[i]->type))
|
||||
continue;
|
||||
|
||||
if (flag & BM_SELECT)
|
||||
BM_Select(bm, data[i], 1);
|
||||
BM_SetHFlag(data[i], flag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -761,16 +764,19 @@ void BMO_HeaderFlag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag)
|
||||
*
|
||||
*/
|
||||
|
||||
void BMO_UnHeaderFlag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag)
|
||||
void BMO_UnHeaderFlag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag, int type)
|
||||
{
|
||||
BMOpSlot *slot = BMO_GetSlot(op, slotname);
|
||||
BMHeader **data = slot->data.p;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < slot->len; i++) {
|
||||
BM_ClearHFlag(data[i], flag);
|
||||
if (!(type & data[i]->type))
|
||||
continue;
|
||||
|
||||
if (flag & BM_SELECT)
|
||||
BM_Select(bm, data[i], 0);
|
||||
BM_ClearHFlag(data[i], flag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -783,14 +789,18 @@ void BMO_UnHeaderFlag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag
|
||||
*
|
||||
*/
|
||||
|
||||
void BMO_Flag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag)
|
||||
void BMO_Flag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag, int type)
|
||||
{
|
||||
BMOpSlot *slot = BMO_GetSlot(op, slotname);
|
||||
BMHeader **data = slot->data.p;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < slot->len; i++)
|
||||
for(i = 0; i < slot->len; i++) {
|
||||
if (!(type & data[i]->type))
|
||||
continue;
|
||||
|
||||
BMO_SetFlag(bm, data[i], flag);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -801,14 +811,18 @@ void BMO_Flag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag)
|
||||
*
|
||||
*/
|
||||
|
||||
void BMO_Unflag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag)
|
||||
void BMO_Unflag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag, int type)
|
||||
{
|
||||
BMOpSlot *slot = BMO_GetSlot(op, slotname);
|
||||
BMHeader **data = slot->data.p;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < slot->len; i++)
|
||||
for(i = 0; i < slot->len; i++) {
|
||||
if (!(type & data[i]->type))
|
||||
continue;
|
||||
|
||||
BMO_ClearFlag(bm, data[i], flag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -41,5 +41,10 @@ void bmesh_edgerotate_exec(BMesh *bm, BMOperator *op);
|
||||
void bmesh_regionextend_exec(BMesh *bm, BMOperator *op);
|
||||
void bmesh_righthandfaces_exec(BMesh *bm, BMOperator *op);
|
||||
void bmesh_vertexsmooth_exec(BMesh *bm, BMOperator *op);
|
||||
void bmesh_extrude_onlyedge_exec(BMesh *bm, BMOperator *op);
|
||||
void bmesh_extrude_face_indiv_exec(BMesh *bm, BMOperator *op);
|
||||
void bmesh_collapsecon_exec(BMesh *bm, BMOperator *op);
|
||||
void bmesh_pointmerge_exec(BMesh *bm, BMOperator *op);
|
||||
void bmesh_collapse_exec(BMesh *bm, BMOperator *op);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BKE_customdata.h"
|
||||
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
|
||||
#include "BLI_mempool.h"
|
||||
|
||||
#include "bmesh_private.h"
|
||||
@@ -65,6 +72,11 @@ typedef struct edgeringWalker {
|
||||
BMLoop *l;
|
||||
} edgeringWalker;
|
||||
|
||||
typedef struct uvedgeWalker {
|
||||
struct uvedgeWalker *prev;
|
||||
BMLoop *l;
|
||||
} uvedgeWalker;
|
||||
|
||||
/* NOTE: this comment is out of date, update it - joeedh
|
||||
* BMWalker - change this to use the filters functions.
|
||||
*
|
||||
@@ -117,6 +129,10 @@ static void edgeringWalker_begin(BMWalker *walker, void *data);
|
||||
static void *edgeringWalker_yield(BMWalker *walker);
|
||||
static void *edgeringWalker_step(BMWalker *walker);
|
||||
|
||||
static void uvedgeWalker_begin(BMWalker *walker, void *data);
|
||||
static void *uvedgeWalker_yield(BMWalker *walker);
|
||||
static void *uvedgeWalker_step(BMWalker *walker);
|
||||
|
||||
/* Pointer hiding*/
|
||||
typedef struct bmesh_walkerGeneric{
|
||||
struct bmesh_walkerGeneric *prev;
|
||||
@@ -126,7 +142,7 @@ typedef struct bmesh_walkerGeneric{
|
||||
void *BMW_Begin(BMWalker *walker, void *start) {
|
||||
walker->begin(walker, start);
|
||||
|
||||
return walker->step(walker);
|
||||
return walker->currentstate ? walker->step(walker) : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -138,11 +154,13 @@ void *BMW_Begin(BMWalker *walker, void *start) {
|
||||
*
|
||||
*/
|
||||
|
||||
void BMW_Init(BMWalker *walker, BMesh *bm, int type, int searchmask)
|
||||
void BMW_Init(BMWalker *walker, BMesh *bm, int type, int searchmask, int flag)
|
||||
{
|
||||
int size = 0;
|
||||
|
||||
memset(walker, 0, sizeof(BMWalker));
|
||||
|
||||
walker->flag = flag;
|
||||
walker->bm = bm;
|
||||
walker->restrictflag = searchmask;
|
||||
walker->visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
|
||||
@@ -184,6 +202,12 @@ void BMW_Init(BMWalker *walker, BMesh *bm, int type, int searchmask)
|
||||
walker->yield = edgeringWalker_yield;
|
||||
size = sizeof(edgeringWalker);
|
||||
break;
|
||||
case BMW_UVISLAND:
|
||||
walker->begin = uvedgeWalker_begin;
|
||||
walker->step = uvedgeWalker_step;
|
||||
walker->yield = uvedgeWalker_yield;
|
||||
size = sizeof(uvedgeWalker);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -291,27 +315,71 @@ void BMW_reset(BMWalker *walker) {
|
||||
*/
|
||||
|
||||
static void shellWalker_begin(BMWalker *walker, void *data){
|
||||
BMIter eiter;
|
||||
BMEdge *e;
|
||||
BMVert *v = data;
|
||||
shellWalker *shellWalk = NULL;
|
||||
|
||||
if (!v->edge)
|
||||
return;
|
||||
|
||||
if (walker->restrictflag) {
|
||||
BM_ITER(e, &eiter, walker->bm, BM_EDGES_OF_VERT, v) {
|
||||
if (BMO_TestFlag(walker->bm, e, walker->restrictflag))
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
e = v->edge;
|
||||
}
|
||||
|
||||
if (!e)
|
||||
return;
|
||||
|
||||
BMW_pushstate(walker);
|
||||
|
||||
shellWalk = walker->currentstate;
|
||||
shellWalk->base = NULL;
|
||||
shellWalk->curedge = NULL;
|
||||
|
||||
if(v->edge){
|
||||
shellWalk->base = v;
|
||||
shellWalk->curedge = v->edge;
|
||||
BLI_ghash_insert(walker->visithash, v->edge, NULL);
|
||||
}
|
||||
shellWalk->base = v;
|
||||
shellWalk->curedge = e;
|
||||
BLI_ghash_insert(walker->visithash, e, NULL);
|
||||
}
|
||||
|
||||
static void *shellWalker_yield(BMWalker *walker)
|
||||
{
|
||||
shellWalker *shellWalk = walker->currentstate;
|
||||
return shellWalk->curedge;
|
||||
}
|
||||
|
||||
static void *shellWalker_step(BMWalker *walker)
|
||||
{
|
||||
shellWalker *swalk = walker->currentstate;
|
||||
BMEdge *e, *e2;
|
||||
BMVert *v;
|
||||
BMIter iter;
|
||||
int i;
|
||||
|
||||
BMW_popstate(walker);
|
||||
|
||||
e = swalk->curedge;
|
||||
for (i=0; i<2; i++) {
|
||||
v = i ? e->v2 : e->v1;
|
||||
BM_ITER(e2, &iter, walker->bm, BM_EDGES_OF_VERT, v) {
|
||||
if (walker->restrictflag && !BMO_TestFlag(walker->bm, e2, walker->restrictflag))
|
||||
continue;
|
||||
if (BLI_ghash_haskey(walker->visithash, e2))
|
||||
continue;
|
||||
|
||||
BMW_pushstate(walker);
|
||||
BLI_ghash_insert(walker->visithash, e2, NULL);
|
||||
|
||||
swalk = walker->currentstate;
|
||||
swalk->curedge = e2;
|
||||
}
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void *shellWalker_step(BMWalker *walker)
|
||||
{
|
||||
BMEdge *curedge, *next = NULL;
|
||||
@@ -324,19 +392,19 @@ static void *shellWalker_step(BMWalker *walker)
|
||||
|
||||
BMW_popstate(walker);
|
||||
|
||||
|
||||
/*find the next edge whose other vertex has not been visited*/
|
||||
curedge = shellWalk.curedge;
|
||||
do{
|
||||
if (!BLI_ghash_haskey(walker->visithash, curedge)) {
|
||||
BLI_ghash_insert(walker->visithash, curedge, NULL);
|
||||
|
||||
if(!(walker->restrictflag &&
|
||||
!BMO_TestFlag(walker->bm, curedge, walker->restrictflag)))
|
||||
if(!walker->restrictflag || (walker->restrictflag &&
|
||||
BMO_TestFlag(walker->bm, curedge, walker->restrictflag)))
|
||||
{
|
||||
ov = BM_OtherEdgeVert(curedge, shellWalk.base);
|
||||
|
||||
/*push a new state onto the stack*/
|
||||
BMW_pushstate(walker);
|
||||
BLI_ghash_insert(walker->visithash, curedge, NULL);
|
||||
|
||||
/*populate the new state*/
|
||||
|
||||
@@ -349,6 +417,7 @@ static void *shellWalker_step(BMWalker *walker)
|
||||
|
||||
return shellWalk.curedge;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Island Boundary Walker:
|
||||
*
|
||||
@@ -757,3 +826,90 @@ static void *edgeringWalker_step(BMWalker *walker)
|
||||
return e;
|
||||
}
|
||||
|
||||
static void uvedgeWalker_begin(BMWalker *walker, void *data)
|
||||
{
|
||||
uvedgeWalker *lwalk;
|
||||
BMLoop *l = data;
|
||||
|
||||
if (BLI_ghash_haskey(walker->visithash, l))
|
||||
return;
|
||||
|
||||
BMW_pushstate(walker);
|
||||
lwalk = walker->currentstate;
|
||||
lwalk->l = l;
|
||||
BLI_ghash_insert(walker->visithash, l, NULL);
|
||||
}
|
||||
|
||||
static void *uvedgeWalker_yield(BMWalker *walker)
|
||||
{
|
||||
uvedgeWalker *lwalk = walker->currentstate;
|
||||
|
||||
if (!lwalk) return NULL;
|
||||
}
|
||||
|
||||
static int walker_compare_uv(MLoopUV *luv1, MLoopUV *luv2)
|
||||
{
|
||||
float udelta = luv1->uv[0] - luv2->uv[0];
|
||||
float vdelta = luv1->uv[1] - luv2->uv[1];
|
||||
|
||||
/*BMESH_TODO: look up proper threshold value*/
|
||||
return udelta*udelta + vdelta*vdelta < 0.0001f;
|
||||
}
|
||||
|
||||
static void *uvedgeWalker_step(BMWalker *walker)
|
||||
{
|
||||
uvedgeWalker *lwalk = walker->currentstate;
|
||||
BMLoop *l, *l2, *l3, *nl, *cl;
|
||||
BMIter liter;
|
||||
void *d1, *d2;
|
||||
int i, j, rlen, type;
|
||||
|
||||
l = lwalk->l;
|
||||
nl = l->head.next;
|
||||
type = walker->bm->ldata.layers[walker->flag].type;
|
||||
|
||||
BMW_popstate(walker);
|
||||
|
||||
if (walker->restrictflag && !BMO_TestFlag(walker->bm, l->e, walker->restrictflag))
|
||||
return l;
|
||||
|
||||
/*go over loops around l->v and nl->v and see which ones share l and nl's
|
||||
mloopuv's coordinates. in addition, push on l->head.next if necassary.*/
|
||||
for (i=0; i<2; i++) {
|
||||
BM_ITER(l2, &liter, walker->bm, BM_LOOPS_OF_VERT, i?nl->v:l->v) {
|
||||
cl = i ? nl : l;
|
||||
|
||||
d1 = CustomData_bmesh_get_layer_n(&walker->bm->ldata,
|
||||
cl->head.data, walker->flag);
|
||||
|
||||
rlen = BM_Edge_FaceCount(l2->e);
|
||||
for (j=0; j<rlen; j++) {
|
||||
if (BLI_ghash_haskey(walker->visithash, l2))
|
||||
continue;
|
||||
if (walker->restrictflag && !(BMO_TestFlag(walker->bm, l2->e, walker->restrictflag)))
|
||||
{
|
||||
if (l2->v != l->v)
|
||||
continue;
|
||||
}
|
||||
|
||||
l3 = l2->v != cl->v ? (BMLoop*)l2->head.next : l2;
|
||||
d2 = CustomData_bmesh_get_layer_n(&walker->bm->ldata,
|
||||
l3->head.data, walker->flag);
|
||||
|
||||
if (!CustomData_data_equals(type, d1, d2))
|
||||
continue;
|
||||
|
||||
BMW_pushstate(walker);
|
||||
BLI_ghash_insert(walker->visithash, l2, NULL);
|
||||
lwalk = walker->currentstate;
|
||||
|
||||
lwalk->l = l2;
|
||||
|
||||
l2 = l2->radial.next->data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
@@ -315,7 +315,8 @@ void dupeop_exec(BMesh *bm, BMOperator *op)
|
||||
BMOperator *dupeop = op;
|
||||
|
||||
/*flag input*/
|
||||
BMO_Flag_Buffer(bm, dupeop, "geom", DUPE_INPUT);
|
||||
BMO_Flag_Buffer(bm, dupeop, "geom", DUPE_INPUT, BM_ALL);
|
||||
|
||||
/*use the internal copy function*/
|
||||
copy_mesh(dupeop, bm, bm);
|
||||
|
||||
@@ -380,7 +381,7 @@ void splitop_exec(BMesh *bm, BMOperator *op)
|
||||
BMO_CopySlot(splitop, &dupeop, "geom", "geom");
|
||||
BMO_Exec_Op(bm, &dupeop);
|
||||
|
||||
BMO_Flag_Buffer(bm, splitop, "geom", SPLIT_INPUT);
|
||||
BMO_Flag_Buffer(bm, splitop, "geom", SPLIT_INPUT, BM_ALL);
|
||||
|
||||
/*make sure to remove edges and verts we don't need.*/
|
||||
for (e= BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);e;e=BMIter_Step(&iter)) {
|
||||
@@ -437,7 +438,7 @@ void delop_exec(BMesh *bm, BMOperator *op)
|
||||
BMOperator *delop = op;
|
||||
|
||||
/*Mark Buffers*/
|
||||
BMO_Flag_Buffer(bm, delop, "geom", DEL_INPUT);
|
||||
BMO_Flag_Buffer(bm, delop, "geom", DEL_INPUT, BM_ALL);
|
||||
|
||||
delete_context(bm, BMO_Get_Int(op, "context"));
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ void connectverts_exec(BMesh *bm, BMOperator *op)
|
||||
V_DECLARE(verts);
|
||||
int i;
|
||||
|
||||
BMO_Flag_Buffer(bm, op, "verts", VERT_INPUT);
|
||||
BMO_Flag_Buffer(bm, op, "verts", VERT_INPUT, BM_VERT);
|
||||
|
||||
for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); f; f=BMIter_Step(&iter)){
|
||||
V_RESET(loops);
|
||||
|
||||
@@ -26,7 +26,7 @@ static int check_hole_in_region(BMesh *bm, BMFace *f) {
|
||||
|
||||
/*checks if there are any unmarked boundary edges in the face region*/
|
||||
|
||||
BMW_Init(®walker, bm, BMW_ISLAND, FACE_MARK);
|
||||
BMW_Init(®walker, bm, BMW_ISLAND, FACE_MARK, 0);
|
||||
f2 = BMW_Begin(®walker, f);
|
||||
for (; f2; f2=BMW_Step(®walker)) {
|
||||
l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_FACE, f2);
|
||||
@@ -59,7 +59,7 @@ void dissolvefaces_exec(BMesh *bm, BMOperator *op)
|
||||
BMWalker regwalker;
|
||||
int i, j, fcopied;
|
||||
|
||||
BMO_Flag_Buffer(bm, op, "faces", FACE_MARK);
|
||||
BMO_Flag_Buffer(bm, op, "faces", FACE_MARK, BM_FACE);
|
||||
|
||||
/*collect regions*/
|
||||
f = BMO_IterNew(&oiter, bm, op, "faces", BM_FACE);
|
||||
@@ -70,7 +70,7 @@ void dissolvefaces_exec(BMesh *bm, BMOperator *op)
|
||||
region = NULL; /*forces different allocation*/
|
||||
|
||||
/*yay, walk!*/
|
||||
BMW_Init(®walker, bm, BMW_ISLAND, FACE_MARK);
|
||||
BMW_Init(®walker, bm, BMW_ISLAND, FACE_MARK, 0);
|
||||
f2 = BMW_Begin(®walker, f);
|
||||
for (; f2; f2=BMW_Step(®walker)) {
|
||||
l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_FACE, f2);
|
||||
@@ -91,7 +91,7 @@ void dissolvefaces_exec(BMesh *bm, BMOperator *op)
|
||||
}
|
||||
BMW_End(®walker);
|
||||
|
||||
BMW_Init(®walker, bm, BMW_ISLAND, FACE_MARK);
|
||||
BMW_Init(®walker, bm, BMW_ISLAND, FACE_MARK, 0);
|
||||
f2 = BMW_Begin(®walker, f);
|
||||
for (; f2; f2=BMW_Step(®walker)) {
|
||||
BMO_ClearFlag(bm, f2, FACE_MARK);
|
||||
@@ -313,7 +313,7 @@ void dissolveverts_exec(BMesh *bm, BMOperator *op)
|
||||
int i;
|
||||
|
||||
vinput = BMO_GetSlot(op, "verts");
|
||||
BMO_Flag_Buffer(bm, op, "verts", VERT_MARK);
|
||||
BMO_Flag_Buffer(bm, op, "verts", VERT_MARK, BM_VERT);
|
||||
|
||||
for (v=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); v; v=BMIter_Step(&iter)) {
|
||||
if (BMO_TestFlag(bm, v, VERT_MARK)) {
|
||||
|
||||
@@ -10,10 +10,129 @@
|
||||
#include "bmesh.h"
|
||||
#include "bmesh_operators_private.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define EXT_INPUT 1
|
||||
#define EXT_KEEP 2
|
||||
#define EXT_DEL 4
|
||||
|
||||
void bmesh_extrude_face_indiv_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
BMOIter siter;
|
||||
BMIter liter, liter2;
|
||||
BMFace *f, *f2, *f3;
|
||||
BMLoop *l, *l2, *l3, *l4;
|
||||
BMEdge **edges = NULL, *e, *laste;
|
||||
BMVert *v, *lastv, *firstv;
|
||||
V_DECLARE(edges);
|
||||
int i;
|
||||
|
||||
BMO_ITER(f, &siter, bm, op, "faces", BM_FACE) {
|
||||
V_RESET(edges);
|
||||
i = 0;
|
||||
firstv = lastv = NULL;
|
||||
BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
|
||||
V_GROW(edges);
|
||||
|
||||
v = BM_Make_Vert(bm, l->v->co, NULL);
|
||||
BM_Copy_Attributes(bm, bm, l->v, v);
|
||||
|
||||
if (lastv) {
|
||||
e = BM_Make_Edge(bm, lastv, v, l->e, 0);
|
||||
edges[i++] = e;
|
||||
}
|
||||
|
||||
lastv = v;
|
||||
laste = l->e;
|
||||
if (!firstv) firstv = v;
|
||||
}
|
||||
|
||||
V_GROW(edges);
|
||||
e = BM_Make_Edge(bm, v, firstv, laste, 0);
|
||||
edges[i++] = e;
|
||||
|
||||
BMO_SetFlag(bm, f, EXT_DEL);
|
||||
|
||||
f2 = BM_Make_Ngon(bm, edges[0]->v1, edges[0]->v2, edges, f->len, 0);
|
||||
BMO_SetFlag(bm, f2, EXT_KEEP);
|
||||
BM_Copy_Attributes(bm, bm, f, f2);
|
||||
|
||||
l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_FACE, f2);
|
||||
BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
|
||||
BM_Copy_Attributes(bm, bm, l, l2);
|
||||
l3 = l->head.next;
|
||||
l4 = l2->head.next;
|
||||
|
||||
f3 = BM_Make_QuadTri(bm, l3->v, l4->v, l2->v, l->v, f, 0);
|
||||
|
||||
BM_Copy_Attributes(bm, bm, l->head.next, f3->loopbase);
|
||||
BM_Copy_Attributes(bm, bm, l->head.next, f3->loopbase->head.next);
|
||||
BM_Copy_Attributes(bm, bm, l, f3->loopbase->head.next->next);
|
||||
BM_Copy_Attributes(bm, bm, l, f3->loopbase->head.next->next->next);
|
||||
|
||||
l2 = BMIter_Step(&liter2);
|
||||
}
|
||||
}
|
||||
|
||||
BMO_CallOpf(bm, "del geom=%ff context=%d", EXT_DEL, DEL_ONLYFACES);
|
||||
|
||||
BMO_Flag_To_Slot(bm, op, "faceout", EXT_KEEP, BM_FACE);
|
||||
}
|
||||
|
||||
void bmesh_extrude_onlyedge_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
BMOIter siter;
|
||||
BMOperator dupeop;
|
||||
BMVert *v1, *v2, *v3, *v4;
|
||||
BMEdge *e, *e2;
|
||||
BMFace *f;
|
||||
|
||||
BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
|
||||
BMO_SetFlag(bm, e, EXT_INPUT);
|
||||
BMO_SetFlag(bm, e->v1, EXT_INPUT);
|
||||
BMO_SetFlag(bm, e->v2, EXT_INPUT);
|
||||
}
|
||||
|
||||
BMO_InitOpf(bm, &dupeop, "dupe geom=%fve", EXT_INPUT);
|
||||
BMO_Exec_Op(bm, &dupeop);
|
||||
|
||||
e = BMO_IterNew(&siter, bm, &dupeop, "boundarymap", 0);
|
||||
for (; e; e=BMO_IterStep(&siter)) {
|
||||
e2 = BMO_IterMapVal(&siter);
|
||||
e2 = *(BMEdge**)e2;
|
||||
|
||||
if (e->loop && e->v1 != e->loop->v) {
|
||||
v1 = e->v1;
|
||||
v2 = e->v2;
|
||||
v3 = e2->v2;
|
||||
v4 = e2->v1;
|
||||
} else {
|
||||
v1 = e2->v1;
|
||||
v2 = e2->v2;
|
||||
v3 = e->v2;
|
||||
v4 = e->v1;
|
||||
}
|
||||
/*not sure what to do about example face, pass NULL for now.*/
|
||||
f = BM_Make_QuadTri(bm, v1, v2, v3, v4, NULL, 0);
|
||||
|
||||
if (BMO_TestFlag(bm, e, EXT_INPUT))
|
||||
e = e2;
|
||||
|
||||
BMO_SetFlag(bm, f, EXT_KEEP);
|
||||
BMO_SetFlag(bm, e, EXT_KEEP);
|
||||
BMO_SetFlag(bm, e->v1, EXT_KEEP);
|
||||
BMO_SetFlag(bm, e->v2, EXT_KEEP);
|
||||
|
||||
}
|
||||
|
||||
BMO_Finish_Op(bm, &dupeop);
|
||||
|
||||
BMO_Flag_To_Slot(bm, op, "geomout", EXT_KEEP, BM_ALL);
|
||||
}
|
||||
|
||||
void extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
BMOIter siter;
|
||||
@@ -45,12 +164,12 @@ void extrude_edge_context_exec(BMesh *bm, BMOperator *op)
|
||||
BMLoop *l, *l2;
|
||||
BMVert *verts[4], *v, *v2;
|
||||
BMFace *f;
|
||||
int rlen, found, delorig=0, i, reverse;
|
||||
int rlen, found, delorig=0, i;
|
||||
|
||||
/*initialize our sub-operators*/
|
||||
BMO_Init_Op(&dupeop, "dupe");
|
||||
|
||||
BMO_Flag_Buffer(bm, op, "edgefacein", EXT_INPUT);
|
||||
BMO_Flag_Buffer(bm, op, "edgefacein", EXT_INPUT, BM_EDGE|BM_FACE);
|
||||
|
||||
/*if one flagged face is bordered by an unflagged face, then we delete
|
||||
original geometry.*/
|
||||
|
||||
@@ -56,7 +56,7 @@ void bmesh_mirror_exec(BMesh *bm, BMOperator *op) {
|
||||
BMO_InitOpf(bm, &dupeop, "dupe geom=%s", op, "geom");
|
||||
BMO_Exec_Op(bm, &dupeop);
|
||||
|
||||
BMO_Flag_Buffer(bm, &dupeop, "newout", ELE_NEW);
|
||||
BMO_Flag_Buffer(bm, &dupeop, "newout", ELE_NEW, BM_ALL);
|
||||
|
||||
/*create old -> new mapping*/
|
||||
i = 0;
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_blenlib.h"
|
||||
|
||||
#include "bmesh.h"
|
||||
#include "mesh_intern.h"
|
||||
#include "bmesh_private.h"
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_ghash.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -157,7 +164,7 @@ void bmesh_weldverts_exec(BMesh *bm, BMOperator *op)
|
||||
v2 = BMO_Get_MapPointer(bm, op, "targetmap", v2);
|
||||
|
||||
|
||||
f2 = BM_Make_Ngon(bm, v2, v, edges, a, 0);
|
||||
f2 = BM_Make_Ngon(bm, v, v2, edges, a, 0);
|
||||
if (f2) {
|
||||
BM_Copy_Attributes(bm, bm, f, f2);
|
||||
BMO_SetFlag(bm, f, ELE_DEL);
|
||||
@@ -195,6 +202,128 @@ static int vergaverco(const void *e1, const void *e2)
|
||||
#define VERT_DOUBLE 2
|
||||
#define VERT_TARGET 4
|
||||
#define VERT_KEEP 8
|
||||
#define VERT_MARK 16
|
||||
|
||||
#define EDGE_MARK 1
|
||||
|
||||
void bmesh_pointmerge_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
}
|
||||
|
||||
void bmesh_collapse_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
BMOperator weldop;
|
||||
BMWalker walker;
|
||||
BMOIter siter;
|
||||
BMIter iter, liter, liter2;
|
||||
BMVert *v;
|
||||
BMEdge *e, **edges = NULL;
|
||||
V_DECLARE(edges);
|
||||
float min[3], max[3];
|
||||
int i, tot;
|
||||
|
||||
BMO_CallOpf(bm, "collapse_uvs edges=%s", op, "edges");
|
||||
BMO_Init_Op(&weldop, "weldverts");
|
||||
|
||||
BMO_Flag_Buffer(bm, op, "edges", EDGE_MARK, BM_EDGE);
|
||||
BMW_Init(&walker, bm, BMW_SHELL, EDGE_MARK, 0);
|
||||
|
||||
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
|
||||
if (!BMO_TestFlag(bm, e, EDGE_MARK))
|
||||
continue;
|
||||
|
||||
e = BMW_Begin(&walker, e->v1);
|
||||
V_RESET(edges);
|
||||
|
||||
INIT_MINMAX(min, max);
|
||||
for (tot=0; e; tot++, e=BMW_Step(&walker)) {
|
||||
V_GROW(edges);
|
||||
edges[tot] = e;
|
||||
|
||||
DO_MINMAX(e->v1->co, min, max);
|
||||
DO_MINMAX(e->v2->co, min, max);
|
||||
}
|
||||
|
||||
VECADD(min, min, max);
|
||||
VECMUL(min, 0.5f);
|
||||
|
||||
/*snap edges to a point. for initial testing purposes anyway.*/
|
||||
for (i=0; i<tot; i++) {
|
||||
VECCOPY(edges[i]->v1->co, min);
|
||||
VECCOPY(edges[i]->v2->co, min);
|
||||
|
||||
if (edges[i]->v1 != edges[0]->v1)
|
||||
BMO_Insert_MapPointer(bm, &weldop, "targetmap", edges[i]->v1, edges[0]->v1);
|
||||
if (edges[i]->v2 != edges[0]->v1)
|
||||
BMO_Insert_MapPointer(bm, &weldop, "targetmap", edges[i]->v2, edges[0]->v1);
|
||||
}
|
||||
}
|
||||
|
||||
BMO_Exec_Op(bm, &weldop);
|
||||
BMO_Finish_Op(bm, &weldop);
|
||||
|
||||
BMW_End(&walker);
|
||||
V_FREE(edges);
|
||||
}
|
||||
|
||||
/*uv collapse function*/
|
||||
void bmesh_collapsecon_do_layer(BMesh *bm, BMOperator *op, int layer)
|
||||
{
|
||||
BMIter iter, liter, liter2;
|
||||
BMFace *f;
|
||||
BMLoop *l, *l2;
|
||||
BMEdge *e;
|
||||
BMVert *v;
|
||||
BMWalker walker;
|
||||
void **blocks = NULL;
|
||||
V_DECLARE(blocks);
|
||||
CDBlockBytes min, max;
|
||||
int i, tot, type = bm->ldata.layers[layer].type;
|
||||
|
||||
BMO_Flag_Buffer(bm, op, "edges", EDGE_MARK, BM_EDGE);
|
||||
|
||||
BMW_Init(&walker, bm, BMW_UVISLAND, EDGE_MARK, layer);
|
||||
|
||||
BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
|
||||
BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
|
||||
if (BMO_TestFlag(bm, l->e, EDGE_MARK)) {
|
||||
/*walk*/
|
||||
V_RESET(blocks);
|
||||
tot = 0;
|
||||
l2 = BMW_Begin(&walker, l);
|
||||
|
||||
CustomData_data_initminmax(type, &min, &max);
|
||||
for (tot=0; l2; tot++, l2=BMW_Step(&walker)) {
|
||||
V_GROW(blocks);
|
||||
blocks[tot] = CustomData_bmesh_get_layer_n(&bm->ldata, l2->head.data, layer);
|
||||
CustomData_data_dominmax(type, blocks[tot], &min, &max);
|
||||
}
|
||||
|
||||
CustomData_data_multiply(type, &min, 0.5f);
|
||||
CustomData_data_multiply(type, &max, 0.5f);
|
||||
CustomData_data_add(type, &min, &max);
|
||||
|
||||
/*snap CD (uv, vcol) points to their centroid*/
|
||||
for (i=0; i<tot; i++) {
|
||||
CustomData_bmesh_set_layer_n(&bm->ldata, blocks[i], layer, &min);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BMW_End(&walker);
|
||||
V_FREE(blocks);
|
||||
}
|
||||
|
||||
void bmesh_collapsecon_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<bm->ldata.totlayer; i++) {
|
||||
if (CustomData_layer_has_math(&bm->ldata, i))
|
||||
bmesh_collapsecon_do_layer(bm, op, i);
|
||||
}
|
||||
}
|
||||
|
||||
void bmesh_removedoubles_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
@@ -275,7 +404,7 @@ void bmesh_finddoubles_exec(BMesh *bm, BMOperator *op)
|
||||
/*sort by vertex coordinates added together*/
|
||||
//qsort(verts, V_COUNT(verts), sizeof(void*), vergaverco);
|
||||
|
||||
BMO_Flag_Buffer(bm, op, "keepverts", VERT_KEEP);
|
||||
BMO_Flag_Buffer(bm, op, "keepverts", VERT_KEEP, BM_VERT);
|
||||
|
||||
len = V_COUNT(verts);
|
||||
for (i=0; i<len; i++) {
|
||||
|
||||
@@ -631,7 +631,7 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
|
||||
int beauty;
|
||||
int i, j, matched, a, b, numcuts, totesel;
|
||||
|
||||
BMO_Flag_Buffer(bmesh, op, "edges", SUBD_SPLIT);
|
||||
BMO_Flag_Buffer(bmesh, op, "edges", SUBD_SPLIT, BM_EDGE);
|
||||
|
||||
numcuts = BMO_GetSlot(op, "numcuts")->data.i;
|
||||
smooth = BMO_GetSlot(op, "smooth")->data.f;
|
||||
|
||||
@@ -201,7 +201,7 @@ void bmesh_regionextend_exec(BMesh *bm, BMOperator *op)
|
||||
int usefaces = BMO_Get_Int(op, "usefaces");
|
||||
int constrict = BMO_Get_Int(op, "constrict");
|
||||
|
||||
BMO_Flag_Buffer(bm, op, "geom", SEL_ORIG);
|
||||
BMO_Flag_Buffer(bm, op, "geom", SEL_ORIG, BM_ALL);
|
||||
|
||||
if (constrict)
|
||||
bmesh_regionextend_constrict(bm, op, usefaces);
|
||||
@@ -249,7 +249,7 @@ void bmesh_righthandfaces_exec(BMesh *bm, BMOperator *op)
|
||||
startf= NULL;
|
||||
maxx= -1.0e10;
|
||||
|
||||
BMO_Flag_Buffer(bm, op, "faces", FACE_FLAG);
|
||||
BMO_Flag_Buffer(bm, op, "faces", FACE_FLAG, BM_FACE);
|
||||
|
||||
/*find a starting face*/
|
||||
BMO_ITER(f, &siter, bm, op, "faces", BM_FACE) {
|
||||
|
||||
@@ -815,7 +815,7 @@ static void walker_select(BMEditMesh *em, int walkercode, void *start, int selec
|
||||
BMHeader *h;
|
||||
BMWalker walker;
|
||||
|
||||
BMW_Init(&walker, bm, walkercode, 0);
|
||||
BMW_Init(&walker, bm, walkercode, 0, 0);
|
||||
h = BMW_Begin(&walker, start);
|
||||
for (; h; h=BMW_Step(&walker)) {
|
||||
BM_Select(bm, h, select);
|
||||
@@ -1536,7 +1536,7 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event
|
||||
eed = eve->edge;
|
||||
}
|
||||
|
||||
BMW_Init(&walker, em->bm, BMW_SHELL, 0);
|
||||
BMW_Init(&walker, em->bm, BMW_SHELL, 0, 0);
|
||||
e = BMW_Begin(&walker, eed->v1);
|
||||
for (; e; e=BMW_Step(&walker)) {
|
||||
BM_Select(em->bm, e->v1, sel);
|
||||
@@ -1587,7 +1587,7 @@ static int select_linked_exec(bContext *C, wmOperator *op)
|
||||
}
|
||||
}
|
||||
|
||||
BMW_Init(&walker, em->bm, BMW_SHELL, 0);
|
||||
BMW_Init(&walker, em->bm, BMW_SHELL, 0, 0);
|
||||
for (i=0; i<tot; i++) {
|
||||
e = BMW_Begin(&walker, verts[i]);
|
||||
for (; e; e=BMW_Step(&walker)) {
|
||||
@@ -1633,7 +1633,7 @@ static int select_more(bContext *C, wmOperator *op)
|
||||
BM_SELECT, 0, usefaces);
|
||||
|
||||
BMO_Exec_Op(em->bm, &bmop);
|
||||
BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT);
|
||||
BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
|
||||
|
||||
EDBM_selectmode_flush(em);
|
||||
|
||||
@@ -1669,7 +1669,7 @@ static int select_less(bContext *C, wmOperator *op)
|
||||
BM_SELECT, 1, usefaces);
|
||||
|
||||
BMO_Exec_Op(em->bm, &bmop);
|
||||
BMO_UnHeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT);
|
||||
BMO_UnHeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
|
||||
|
||||
EDBM_selectmode_flush(em);
|
||||
|
||||
|
||||
@@ -334,10 +334,37 @@ void MESH_OT_subdivs(wmOperatorType *ot)
|
||||
|
||||
/* individual face extrude */
|
||||
/* will use vertex normals for extrusion directions, so *nor is unaffected */
|
||||
short EDBM_Extrude_face_indiv(BMEditMesh *em, short flag, float *nor)
|
||||
short EDBM_Extrude_face_indiv(BMEditMesh *em, wmOperator *op, short flag, float *nor)
|
||||
{
|
||||
return 'g';
|
||||
BMOIter siter;
|
||||
BMIter liter;
|
||||
BMFace *f;
|
||||
BMLoop *l;
|
||||
BMOperator bmop;
|
||||
|
||||
EDBM_InitOpf(em, &bmop, op, "extrude_face_indiv faces=%hf", flag);
|
||||
|
||||
/*deselect original verts*/
|
||||
EDBM_clear_flag_all(em, BM_SELECT);
|
||||
|
||||
BMO_Exec_Op(em->bm, &bmop);
|
||||
|
||||
BMO_ITER(f, &siter, em->bm, &bmop, "faceout", BM_FACE) {
|
||||
BM_Select(em->bm, f, 1);
|
||||
|
||||
/*set face vertex normals to face normal*/
|
||||
BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
|
||||
VECCOPY(l->v->no, f->no);
|
||||
}
|
||||
}
|
||||
|
||||
if (!EDBM_FinishOp(em, &bmop, op, 1)) return 0;
|
||||
|
||||
return 's'; // s is shrink/fatten
|
||||
}
|
||||
|
||||
#if 0
|
||||
short EDBM_Extrude_face_indiv(BMEditMesh *em, wmOperator *op, short flag, float *nor)
|
||||
EditVert *eve, *v1, *v2, *v3, *v4;
|
||||
EditEdge *eed;
|
||||
EditFace *efa, *nextfa;
|
||||
@@ -421,15 +448,31 @@ short EDBM_Extrude_face_indiv(BMEditMesh *em, short flag, float *nor)
|
||||
EM_select_flush(em);
|
||||
|
||||
return 'n';
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* extrudes individual edges */
|
||||
short EDBM_Extrude_edges_indiv(BMEditMesh *em, wmOperator *op, short flag, float *nor)
|
||||
{
|
||||
BMOperator bmop;
|
||||
|
||||
EDBM_InitOpf(em, &bmop, op, "extrude_edge_only edges=%he", flag);
|
||||
|
||||
/*deselect original verts*/
|
||||
EDBM_clear_flag_all(em, BM_SELECT);
|
||||
|
||||
BMO_Exec_Op(em->bm, &bmop);
|
||||
BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_VERT|BM_EDGE);
|
||||
|
||||
if (!EDBM_FinishOp(em, &bmop, op, 1)) return 0;
|
||||
|
||||
return 'n'; // n is normal grab
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* nor is filled with constraint vector */
|
||||
short EDBM_Extrude_edges_indiv(BMEditMesh *em, short flag, float *nor)
|
||||
{
|
||||
#if 0
|
||||
EditVert *eve;
|
||||
EditEdge *eed;
|
||||
EditFace *efa;
|
||||
@@ -488,25 +531,23 @@ short EDBM_Extrude_edges_indiv(BMEditMesh *em, short flag, float *nor)
|
||||
}
|
||||
|
||||
if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // g is grab
|
||||
#endif
|
||||
return 'n'; // n is for normal constraint
|
||||
}
|
||||
#endif
|
||||
|
||||
/* extrudes individual vertices */
|
||||
short EDBM_Extrude_verts_indiv(BMEditMesh *em, wmOperator *op, short flag, float *nor)
|
||||
{
|
||||
BMOperator bmop;
|
||||
BMOIter siter;
|
||||
BMVert *v;
|
||||
|
||||
EDBM_InitOpf(em, &bmop, op, "extrude_vert_indiv verts=%hv", flag);
|
||||
|
||||
/*deselect original verts*/
|
||||
BMO_UnHeaderFlag_Buffer(em->bm, &bmop, "verts", BM_SELECT);
|
||||
BMO_UnHeaderFlag_Buffer(em->bm, &bmop, "verts", BM_SELECT, BM_VERT);
|
||||
|
||||
BMO_Exec_Op(em->bm, &bmop);
|
||||
BMO_HeaderFlag_Buffer(em->bm, &bmop, "vertout", BM_SELECT, BM_VERT);
|
||||
|
||||
BMO_HeaderFlag_Buffer(em->bm, &bmop, "vertout", BM_SELECT);
|
||||
if (!EDBM_FinishOp(em, &bmop, op, 1)) return 0;
|
||||
|
||||
return 'g'; // g is grab
|
||||
@@ -650,7 +691,6 @@ static int extrude_repeat_mesh(bContext *C, wmOperator *op)
|
||||
int steps = RNA_int_get(op->ptr,"steps");
|
||||
|
||||
float offs = RNA_float_get(op->ptr,"offset");
|
||||
|
||||
float dvec[3], tmat[3][3], bmat[3][3], nor[3]= {0.0, 0.0, 0.0};
|
||||
short a;
|
||||
|
||||
@@ -711,6 +751,7 @@ int EDBM_Extrude_Mesh(Object *obedit, BMEditMesh *em, wmOperator *op, float *nor
|
||||
float *nor = norin ? norin : stacknor;
|
||||
|
||||
nor[0] = nor[1] = nor[2] = 0.0f;
|
||||
|
||||
if(em->selectmode & SCE_SELECT_VERTEX) {
|
||||
if(em->bm->totvertsel==0) nr= 0;
|
||||
else if(em->bm->totvertsel==1) nr= 4;
|
||||
@@ -740,15 +781,15 @@ int EDBM_Extrude_Mesh(Object *obedit, BMEditMesh *em, wmOperator *op, float *nor
|
||||
else
|
||||
nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2");
|
||||
}
|
||||
|
||||
|
||||
if(nr<1) return 'g';
|
||||
|
||||
if(nr==1 && em->selectmode & SCE_SELECT_VERTEX)
|
||||
transmode= EDBM_Extrude_vert(obedit, em, SELECT, nor);
|
||||
else if (nr == 1) transmode= EDBM_Extrude_edge(obedit, em, SELECT, nor);
|
||||
else if(nr==4) transmode= EDBM_Extrude_verts_indiv(em, op, SELECT, nor);
|
||||
else if(nr==3) transmode= EDBM_Extrude_edges_indiv(em, SELECT, nor);
|
||||
else transmode= EDBM_Extrude_face_indiv(em, SELECT, nor);
|
||||
else if(nr==3) transmode= EDBM_Extrude_edges_indiv(em, op, SELECT, nor);
|
||||
else transmode= EDBM_Extrude_face_indiv(em, op, SELECT, nor);
|
||||
|
||||
if(transmode==0) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Not a valid selection for extrude");
|
||||
@@ -784,15 +825,29 @@ int EDBM_Extrude_Mesh(Object *obedit, BMEditMesh *em, wmOperator *op, float *nor
|
||||
return transmode;
|
||||
}
|
||||
|
||||
static int mesh_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
/* extrude without transform */
|
||||
static int mesh_extrude_region_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
|
||||
|
||||
EDBM_Extrude_Mesh(obedit, em, op, NULL);
|
||||
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int mesh_extrude_region_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
|
||||
float nor[3];
|
||||
int constraint_axis[3] = {0, 0, 1};
|
||||
int tmode;
|
||||
|
||||
tmode = EDBM_Extrude_Mesh(obedit, em, op, NULL);
|
||||
tmode = EDBM_Extrude_edge(obedit, em, BM_SELECT, nor);
|
||||
|
||||
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
|
||||
@@ -809,29 +864,15 @@ static int mesh_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
/* extrude without transform */
|
||||
static int mesh_extrude_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
|
||||
|
||||
EDBM_Extrude_Mesh(obedit, em, op, NULL);
|
||||
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
||||
void MESH_OT_extrude(wmOperatorType *ot)
|
||||
void MESH_OT_extrude_region(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Extrude";
|
||||
ot->idname= "MESH_OT_extrude";
|
||||
ot->name= "Extrude Region";
|
||||
ot->idname= "MESH_OT_extrude_region";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= mesh_extrude_invoke;
|
||||
ot->exec= mesh_extrude_exec;
|
||||
ot->invoke= mesh_extrude_region_invoke;
|
||||
ot->exec= mesh_extrude_region_exec;
|
||||
ot->poll= ED_operator_editmesh;
|
||||
|
||||
/* flags */
|
||||
@@ -843,6 +884,296 @@ void MESH_OT_extrude(wmOperatorType *ot)
|
||||
RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
|
||||
}
|
||||
|
||||
static int mesh_extrude_verts_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
|
||||
float nor[3];
|
||||
|
||||
EDBM_Extrude_verts_indiv(em, op, BM_SELECT, nor);
|
||||
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int mesh_extrude_verts_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
|
||||
float nor[3];
|
||||
int constraint_axis[3] = {0, 0, 1};
|
||||
int tmode;
|
||||
|
||||
tmode = EDBM_Extrude_verts_indiv(em, op, BM_SELECT, nor);
|
||||
|
||||
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
|
||||
|
||||
RNA_enum_set(op->ptr, "proportional", 0);
|
||||
RNA_boolean_set(op->ptr, "mirror", 0);
|
||||
|
||||
if (tmode == 'n') {
|
||||
RNA_enum_set(op->ptr, "constraint_orientation", V3D_MANIP_NORMAL);
|
||||
RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
|
||||
}
|
||||
WM_operator_name_call(C, "TFM_OT_translate", WM_OP_INVOKE_REGION_WIN, op->ptr);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void MESH_OT_extrude_verts_indiv(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Extrude Only Vertices";
|
||||
ot->idname= "MESH_OT_extrude_verts_indiv";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= mesh_extrude_verts_invoke;
|
||||
ot->exec= mesh_extrude_verts_exec;
|
||||
ot->poll= ED_operator_editmesh;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
/* to give to transform */
|
||||
Properties_Proportional(ot);
|
||||
Properties_Constraints(ot);
|
||||
RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
|
||||
}
|
||||
|
||||
static int mesh_extrude_edges_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
|
||||
float nor[3];
|
||||
|
||||
EDBM_Extrude_edges_indiv(em, op, BM_SELECT, nor);
|
||||
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int mesh_extrude_edges_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
|
||||
float nor[3];
|
||||
int constraint_axis[3] = {0, 0, 1};
|
||||
int tmode;
|
||||
|
||||
tmode = EDBM_Extrude_edges_indiv(em, op, BM_SELECT, nor);
|
||||
|
||||
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
|
||||
|
||||
RNA_enum_set(op->ptr, "proportional", 0);
|
||||
RNA_boolean_set(op->ptr, "mirror", 0);
|
||||
|
||||
/*if (tmode == 'n') {
|
||||
RNA_enum_set(op->ptr, "constraint_orientation", V3D_MANIP_NORMAL);
|
||||
RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
|
||||
}*/
|
||||
WM_operator_name_call(C, "TFM_OT_translate", WM_OP_INVOKE_REGION_WIN, op->ptr);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void MESH_OT_extrude_edges_indiv(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Extrude Only Edges";
|
||||
ot->idname= "MESH_OT_extrude_edges_indiv";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= mesh_extrude_edges_invoke;
|
||||
ot->exec= mesh_extrude_edges_exec;
|
||||
ot->poll= ED_operator_editmesh;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
/* to give to transform */
|
||||
Properties_Proportional(ot);
|
||||
Properties_Constraints(ot);
|
||||
RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
|
||||
}
|
||||
|
||||
static int mesh_extrude_faces_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
|
||||
float nor[3];
|
||||
|
||||
EDBM_Extrude_face_indiv(em, op, BM_SELECT, nor);
|
||||
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int mesh_extrude_faces_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
|
||||
float nor[3];
|
||||
int constraint_axis[3] = {0, 0, 1};
|
||||
int tmode;
|
||||
|
||||
tmode = EDBM_Extrude_face_indiv(em, op, BM_SELECT, nor);
|
||||
|
||||
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
|
||||
|
||||
RNA_enum_set(op->ptr, "proportional", 0);
|
||||
RNA_boolean_set(op->ptr, "mirror", 0);
|
||||
|
||||
if (tmode == 's') {
|
||||
WM_operator_name_call(C, "TFM_OT_shrink_fatten", WM_OP_INVOKE_REGION_WIN, op->ptr);
|
||||
} else {
|
||||
if (tmode == 'n') {
|
||||
RNA_enum_set(op->ptr, "constraint_orientation", V3D_MANIP_NORMAL);
|
||||
RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
|
||||
}
|
||||
WM_operator_name_call(C, "TFM_OT_translate", WM_OP_INVOKE_REGION_WIN, op->ptr);
|
||||
}
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void MESH_OT_extrude_faces_indiv(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Extrude Individual Faces";
|
||||
ot->idname= "MESH_OT_extrude_faces_indiv";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= mesh_extrude_faces_invoke;
|
||||
ot->exec= mesh_extrude_faces_exec;
|
||||
ot->poll= ED_operator_editmesh;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
/* to give to transform */
|
||||
Properties_Proportional(ot);
|
||||
Properties_Constraints(ot);
|
||||
RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
|
||||
}
|
||||
|
||||
int extrude_menu_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
|
||||
uiPopupMenu *pup;
|
||||
uiLayout *layout;
|
||||
|
||||
if(em->selectmode & SCE_SELECT_VERTEX) {
|
||||
if(em->bm->totvertsel==0) {
|
||||
return OPERATOR_CANCELLED;
|
||||
} else if(em->bm->totvertsel==1) {
|
||||
WM_operator_name_call(C, "MESH_OT_extrude_verts_indiv", WM_OP_INVOKE_REGION_WIN, op->ptr);
|
||||
} else if(em->bm->totedgesel==0) {
|
||||
WM_operator_name_call(C, "MESH_OT_extrude_verts_indiv", WM_OP_INVOKE_REGION_WIN, op->ptr);
|
||||
} else if(em->bm->totfacesel==0) {
|
||||
// pupmenu("Extrude %t|Only Edges%x3|Only Vertices%x4");
|
||||
pup= uiPupMenuBegin(C, "Extrude", 0);
|
||||
layout= uiPupMenuLayout(pup);
|
||||
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
|
||||
|
||||
uiItemO(layout, "Only Edges", 0, "MESH_OT_extrude_edges_indiv");
|
||||
uiItemO(layout, "Only Verts", 0, "MESH_OT_extrude_verts_indiv");
|
||||
|
||||
uiPupMenuEnd(C, pup);
|
||||
} else if(em->bm->totfacesel==1) {
|
||||
// pupmenu("Extrude %t|Region %x1|Only Edges%x3|Only Vertices%x4");
|
||||
pup= uiPupMenuBegin(C, "Extrude", 0);
|
||||
layout= uiPupMenuLayout(pup);
|
||||
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
|
||||
|
||||
uiItemO(layout, "Region", 0, "MESH_OT_extrude_region");
|
||||
uiItemO(layout, "Only Edges", 0, "MESH_OT_extrude_edges_indiv");
|
||||
uiItemO(layout, "Only Verts", 0, "MESH_OT_extrude_verts_indiv");
|
||||
|
||||
uiPupMenuEnd(C, pup);
|
||||
} else {
|
||||
// pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4");
|
||||
pup= uiPupMenuBegin(C, "Extrude", 0);
|
||||
layout= uiPupMenuLayout(pup);
|
||||
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
|
||||
|
||||
uiItemO(layout, "Region", 0, "MESH_OT_extrude_region");
|
||||
uiItemO(layout, "Individual Faces", 0, "MESH_OT_extrude_faces_indiv");
|
||||
uiItemO(layout, "Only Edges", 0, "MESH_OT_extrude_edges_indiv");
|
||||
uiItemO(layout, "Only Verts", 0, "MESH_OT_extrude_verts_indiv");
|
||||
|
||||
uiPupMenuEnd(C, pup);
|
||||
}
|
||||
} else if (em->selectmode & SCE_SELECT_EDGE) {
|
||||
if (em->bm->totedge==0)
|
||||
return OPERATOR_CANCELLED;
|
||||
else if (em->bm->totedgesel==1)
|
||||
WM_operator_name_call(C, "MESH_OT_extrude_edges_indiv", WM_OP_INVOKE_REGION_WIN, op->ptr);
|
||||
else if (em->bm->totfacesel==0) {
|
||||
WM_operator_name_call(C, "MESH_OT_extrude_edges_indiv", WM_OP_INVOKE_REGION_WIN, op->ptr);
|
||||
} else if (em->bm->totfacesel==1) {
|
||||
// pupmenu("Extrude %t|Region %x1|Only Edges%x3");
|
||||
pup= uiPupMenuBegin(C, "Extrude", 0);
|
||||
layout= uiPupMenuLayout(pup);
|
||||
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
|
||||
|
||||
uiItemO(layout, "Region", 0, "MESH_OT_extrude_region");
|
||||
uiItemO(layout, "Only Edges", 0, "MESH_OT_extrude_edges_indiv");
|
||||
|
||||
uiPupMenuEnd(C, pup);
|
||||
} else {
|
||||
// pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3");
|
||||
pup= uiPupMenuBegin(C, "Extrude", 0);
|
||||
layout= uiPupMenuLayout(pup);
|
||||
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
|
||||
|
||||
uiItemO(layout, "Region", 0, "MESH_OT_extrude_region");
|
||||
uiItemO(layout, "Individual Faces", 0, "MESH_OT_extrude_faces_indiv");
|
||||
uiItemO(layout, "Only Edges", 0, "MESH_OT_extrude_edges_indiv");
|
||||
|
||||
uiPupMenuEnd(C, pup);
|
||||
}
|
||||
|
||||
} else if (em->selectmode & SCE_SELECT_FACE) {
|
||||
if (em->bm->totfacesel==0)
|
||||
return OPERATOR_CANCELLED;
|
||||
else if (em->bm->totfacesel==1)
|
||||
WM_operator_name_call(C, "MESH_OT_extrude_region", WM_OP_INVOKE_REGION_WIN, op->ptr);
|
||||
else {
|
||||
// pupmenu("Extrude %t|Region %x1||Individual Faces %x2");
|
||||
pup= uiPupMenuBegin(C, "Extrude", 0);
|
||||
layout= uiPupMenuLayout(pup);
|
||||
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
|
||||
|
||||
uiItemO(layout, "Region", 0, "MESH_OT_extrude_region");
|
||||
uiItemO(layout, "Individual Faces", 0, "MESH_OT_extrude_faces_indiv");
|
||||
|
||||
uiPupMenuEnd(C, pup);
|
||||
}
|
||||
}
|
||||
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
void MESH_OT_extrude(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Extrude";
|
||||
ot->idname= "MESH_OT_extrude";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= extrude_menu_invoke;
|
||||
ot->poll= ED_operator_editmesh;
|
||||
}
|
||||
|
||||
/* ******************** (de)select all operator **************** */
|
||||
|
||||
void EDBM_toggle_select_all(BMEditMesh *em) /* exported for UV */
|
||||
@@ -1116,7 +1447,7 @@ static int addedgeface_mesh_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
BMO_Exec_Op(em->bm, &bmop);
|
||||
BMO_HeaderFlag_Buffer(em->bm, &bmop, "faceout", BM_SELECT);
|
||||
BMO_HeaderFlag_Buffer(em->bm, &bmop, "faceout", BM_SELECT, BM_FACE);
|
||||
|
||||
if (!EDBM_FinishOp(em, &bmop, op, 1))
|
||||
return OPERATOR_CANCELLED;
|
||||
@@ -1383,7 +1714,7 @@ static int mesh_duplicate_exec(bContext *C, wmOperator *op)
|
||||
BMO_Exec_Op(em->bm, &bmop);
|
||||
EDBM_clear_flag_all(em, BM_SELECT);
|
||||
|
||||
BMO_HeaderFlag_Buffer(em->bm, &bmop, "newout", BM_SELECT);
|
||||
BMO_HeaderFlag_Buffer(em->bm, &bmop, "newout", BM_SELECT, BM_ALL);
|
||||
|
||||
if (!EDBM_FinishOp(em, &bmop, op, 1))
|
||||
return OPERATOR_CANCELLED;
|
||||
@@ -1506,7 +1837,7 @@ static int edge_rotate_selected(bContext *C, wmOperator *op)
|
||||
EDBM_InitOpf(em, &bmop, op, "edgerotate edges=%e ccw=%d", eed, ccw);
|
||||
BMO_Exec_Op(em->bm, &bmop);
|
||||
|
||||
BMO_HeaderFlag_Buffer(em->bm, &bmop, "edgeout", BM_SELECT);
|
||||
BMO_HeaderFlag_Buffer(em->bm, &bmop, "edgeout", BM_SELECT, BM_EDGE);
|
||||
|
||||
if (!EDBM_FinishOp(em, &bmop, op, 1))
|
||||
return OPERATOR_CANCELLED;
|
||||
@@ -1745,3 +2076,66 @@ void MESH_OT_vertices_smooth(wmOperatorType *ot)
|
||||
|
||||
RNA_def_int(ot->srna, "repeat", 1, 1, 100, "Number of times to smooth the mesh", "", 1, INT_MAX);
|
||||
}
|
||||
|
||||
|
||||
static int bm_test_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
|
||||
#if 1
|
||||
if (!EDBM_CallOpf(em, op, "collapse edges=%he", BM_SELECT))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
#else //uv island walker test
|
||||
BMIter iter, liter;
|
||||
BMFace *f;
|
||||
BMLoop *l, *l2;
|
||||
MLoopUV *luv;
|
||||
BMWalker walker;
|
||||
int i=0;
|
||||
|
||||
BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
|
||||
BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
|
||||
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
|
||||
}
|
||||
}
|
||||
|
||||
BMW_Init(&walker, em->bm, BMW_UVISLAND, 0);
|
||||
|
||||
BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
|
||||
BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
|
||||
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
|
||||
if (luv->flag & MLOOPUV_VERTSEL) {
|
||||
l2 = BMW_Begin(&walker, l);
|
||||
for (; l2; l2=BMW_Step(&walker)) {
|
||||
luv = CustomData_bmesh_get(&em->bm->ldata, l2->head.data, CD_MLOOPUV);
|
||||
luv->flag |= MLOOPUV_VERTSEL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BMW_End(&walker);
|
||||
#endif
|
||||
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); //TODO is this needed ?
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void MESH_OT_bm_test(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "BMesh Test Operator";
|
||||
ot->idname= "MESH_OT_bm_test";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= bm_test_exec;
|
||||
ot->poll= ED_operator_editmesh;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
//RNA_def_int(ot->srna, "repeat", 1, 1, 100, "Number of times to smooth the mesh", "", 1, INT_MAX);
|
||||
}
|
||||
|
||||
@@ -410,7 +410,7 @@ void EDBM_select_more(BMEditMesh *em)
|
||||
"regionextend geom=%hvef constrict=%d usefaces=%d",
|
||||
BM_SELECT, 0, usefaces);
|
||||
BMO_Exec_Op(em->bm, &bmop);
|
||||
BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT);
|
||||
BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
|
||||
BMO_Finish_Op(em->bm, &bmop);
|
||||
|
||||
EDBM_selectmode_flush(em);
|
||||
@@ -425,7 +425,7 @@ void EDBM_select_less(BMEditMesh *em)
|
||||
"regionextend geom=%hvef constrict=%d usefaces=%d",
|
||||
BM_SELECT, 0, usefaces);
|
||||
BMO_Exec_Op(em->bm, &bmop);
|
||||
BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT);
|
||||
BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
|
||||
BMO_Finish_Op(em->bm, &bmop);
|
||||
|
||||
EDBM_selectmode_flush(em);
|
||||
|
||||
@@ -1508,34 +1508,6 @@ static int edge_not_in_tagged_face(EditMesh *em, EditEdge *eed)
|
||||
- has vertices with valence 2
|
||||
*/
|
||||
static void edgeloop_select(EditMesh *em, EditEdge *starteed, int select)
|
||||
{
|
||||
BMesh *bm;
|
||||
BMEdge *e;
|
||||
EditMesh *em2;
|
||||
BMOperator op;
|
||||
BMWalker walker;
|
||||
|
||||
bm = init_editmesh_to_bmesh(em, &op);
|
||||
BMO_Exec_Op(bm, &op);
|
||||
|
||||
e = BMO_Get_MapPointer(bm, &op, "map", starteed);
|
||||
|
||||
BMW_Init(&walker, bm, BMW_LOOP, 0);
|
||||
e = BMW_Begin(&walker, e);
|
||||
for (; e; e=BMW_Step(&walker)) {
|
||||
BM_Select(bm, e, 1);
|
||||
}
|
||||
BMW_End(&walker);
|
||||
|
||||
BMO_Finish_Op(bm, &op);
|
||||
|
||||
em2 = bmesh_to_editmesh(bm);
|
||||
BM_Free_Mesh(bm);
|
||||
set_editMesh(em, em2);
|
||||
MEM_freeN(em2);
|
||||
}
|
||||
|
||||
static void edgeloop_select_old(EditMesh *em, EditEdge *starteed, int select)
|
||||
{
|
||||
EditVert *eve;
|
||||
EditEdge *eed;
|
||||
|
||||
@@ -5499,8 +5499,6 @@ static int merge_exec(bContext *C, wmOperator *op)
|
||||
if(!count)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
BKE_reportf(op->reports, RPT_INFO, "Removed %d vertices.", count);
|
||||
|
||||
BKE_mesh_end_editmesh(obedit->data, em);
|
||||
|
||||
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
|
||||
|
||||
@@ -295,6 +295,11 @@ void MESH_OT_sticky_remove(struct wmOperatorType *ot);
|
||||
/* ************* bmesh_tools.c ***********/
|
||||
void MESH_OT_vert_connect(struct wmOperatorType *ot);
|
||||
void MESH_OT_edge_split(struct wmOperatorType *ot);
|
||||
void MESH_OT_extrude_region(struct wmOperatorType *ot);
|
||||
void MESH_OT_extrude_verts_indiv(struct wmOperatorType *ot);
|
||||
void MESH_OT_extrude_edges_indiv(struct wmOperatorType *ot);
|
||||
void MESH_OT_extrude_faces_indiv(struct wmOperatorType *ot);
|
||||
void MESH_OT_bm_test(struct wmOperatorType *ot);
|
||||
|
||||
#endif // MESH_INTERN_H
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ static int vertex_specials_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
uiItemO(layout, "Merge...", 0, "MESH_OT_merge");
|
||||
uiItemO(layout, "Smooth", 0, "MESH_OT_vertices_smooth");
|
||||
uiItemO(layout, "Select Vertex Path", 0, "MESH_OT_select_vertex_path");
|
||||
uiItemO(layout, "BMesh Test Operator", 0, "MESH_OT_bm_test");
|
||||
//uiItemO(layout, "Blend From Shape", 0, "MESH_OT_blend_from_shape");
|
||||
//uiItemO(layout, "Propagate to All Shapes", 0, "MESH_OT_shape_propagate_to_all");
|
||||
|
||||
@@ -231,7 +232,9 @@ static void MESH_OT_specials(wmOperatorType *ot)
|
||||
void ED_operatortypes_mesh(void)
|
||||
{
|
||||
wmOperatorType *ot;
|
||||
|
||||
wmOperatorTypeMacro *otm;
|
||||
static int constraint_axis[3] = {0, 0, 1};
|
||||
|
||||
WM_operatortype_append(MESH_OT_select_all_toggle);
|
||||
WM_operatortype_append(MESH_OT_select_more);
|
||||
WM_operatortype_append(MESH_OT_select_less);
|
||||
@@ -317,7 +320,14 @@ void ED_operatortypes_mesh(void)
|
||||
WM_operatortype_append(MESH_OT_specials);
|
||||
WM_operatortype_append(MESH_OT_vert_connect);
|
||||
WM_operatortype_append(MESH_OT_edge_split);
|
||||
|
||||
WM_operatortype_append(MESH_OT_extrude_region);
|
||||
WM_operatortype_append(MESH_OT_extrude_verts_indiv);
|
||||
WM_operatortype_append(MESH_OT_extrude_edges_indiv);
|
||||
WM_operatortype_append(MESH_OT_extrude_faces_indiv);
|
||||
|
||||
WM_operatortype_append(MESH_OT_bm_test);
|
||||
|
||||
/* macros */
|
||||
ot= WM_operatortype_append_macro("MESH_OT_duplicate_move", "Add Duplicate", OPTYPE_UNDO|OPTYPE_REGISTER);
|
||||
WM_operatortype_macro_define(ot, "MESH_OT_duplicate");
|
||||
@@ -329,7 +339,14 @@ void ED_operatortypes_mesh(void)
|
||||
|
||||
/*ot= WM_operatortype_append_macro("MESH_OT_extrude_move", "Extrude", OPTYPE_UNDO|OPTYPE_REGISTER);
|
||||
WM_operatortype_macro_define(ot, "MESH_OT_extrude");
|
||||
WM_operatortype_macro_define(ot, "TFM_OT_translate");*/
|
||||
otm = WM_operatortype_macro_define(ot, "TFM_OT_translate");
|
||||
|
||||
RNA_enum_set(otm->ptr, "proportional", 0);
|
||||
RNA_boolean_set(otm->ptr, "mirror", 0);
|
||||
|
||||
RNA_enum_set(otm->ptr, "constraint_orientation", V3D_MANIP_NORMAL);
|
||||
RNA_boolean_set_array(otm->ptr, "constraint_axis", constraint_axis);*/
|
||||
|
||||
}
|
||||
|
||||
/* note mesh keymap also for other space? */
|
||||
|
||||
@@ -75,9 +75,11 @@ void WM_operator_free(wmOperator *op)
|
||||
}
|
||||
|
||||
if(op->macro.first) {
|
||||
wmOperator *opm;
|
||||
for(opm= op->macro.first; opm; opm= opm->next)
|
||||
wmOperator *opm, *onext;
|
||||
for(opm= op->macro.first; opm; opm= onext) {
|
||||
onext = opm->next;
|
||||
WM_operator_free(opm);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(op);
|
||||
|
||||
Reference in New Issue
Block a user