Bring back "Sort Faces" command.
This was the old Ctrl + FKEY in object mode, now it's in edit mode and is part of the Ctrl + FKEY menu (Faces). I also assing this to the Ctrl + Alt + FKEY, but Matt please check this and feel free to change (or tell me and I will change). Still there is no "reverse" function, but I commit now to finish in my home.
This commit is contained in:
@@ -1550,6 +1550,7 @@ class VIEW3D_MT_edit_mesh_faces(bpy.types.Menu):
|
||||
layout.operator("mesh.fill")
|
||||
layout.operator("mesh.beautify_fill")
|
||||
layout.operator("mesh.solidify")
|
||||
layout.operator("mesh.sort_faces")
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
|
||||
#include "ED_screen.h"
|
||||
#include "ED_transform.h"
|
||||
#include "ED_view3d.h"
|
||||
#include "ED_object.h"
|
||||
|
||||
|
||||
#include "mesh_intern.h"
|
||||
@@ -7077,6 +7078,184 @@ void MESH_OT_beautify_fill(wmOperatorType *ot)
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ********************** SORT FACES ******************* */
|
||||
|
||||
static void permutate(void *list, int num, int size, int *index)
|
||||
{
|
||||
void *buf;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
len = num * size;
|
||||
|
||||
buf = MEM_mallocN(len, "permutate");
|
||||
memcpy(buf, list, len);
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
memcpy((char *)list + (i * size), (char *)buf + (index[i] * size), size);
|
||||
}
|
||||
MEM_freeN(buf);
|
||||
}
|
||||
|
||||
/* sort faces on view axis */
|
||||
static float *face_sort_floats;
|
||||
static int float_sort(const void *v1, const void *v2)
|
||||
{
|
||||
float x1, x2;
|
||||
|
||||
x1 = face_sort_floats[((int *) v1)[0]];
|
||||
x2 = face_sort_floats[((int *) v2)[0]];
|
||||
|
||||
if( x1 > x2 ) return 1;
|
||||
else if( x1 < x2 ) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int sort_faces_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
RegionView3D *rv3d= ED_view3d_context_rv3d(C);
|
||||
View3D *v3d= CTX_wm_view3d(C);
|
||||
Object *ob= CTX_data_active_object(C);
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
Mesh *me;
|
||||
CustomDataLayer *layer;
|
||||
int i, *index;
|
||||
int event;
|
||||
float reverse = 1;
|
||||
// XXX int ctrl= 0;
|
||||
|
||||
if(!ob) return OPERATOR_FINISHED;
|
||||
if(ob->type!=OB_MESH) return OPERATOR_FINISHED;
|
||||
if (!v3d) return OPERATOR_FINISHED;
|
||||
|
||||
/* This operator work in Object Mode, not in edit mode.
|
||||
* After talk with Cambell we agree that there is no point to port this to EditMesh right now.
|
||||
* so for now, we just exit_editmode and enter_editmode at the end of this function.
|
||||
*/
|
||||
ED_object_exit_editmode(C, EM_FREEDATA);
|
||||
|
||||
me= ob->data;
|
||||
if(me->totface==0) {
|
||||
ED_object_enter_editmode(C, 0);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
event= RNA_enum_get(op->ptr, "type");
|
||||
|
||||
// XXX
|
||||
//if(ctrl)
|
||||
// reverse = -1;
|
||||
|
||||
/* create index list */
|
||||
index= (int *)MEM_mallocN(sizeof(int) * me->totface, "sort faces");
|
||||
for (i = 0; i < me->totface; i++) {
|
||||
index[i] = i;
|
||||
}
|
||||
|
||||
face_sort_floats = (float *) MEM_mallocN(sizeof(float) * me->totface, "sort faces float");
|
||||
|
||||
/* sort index list instead of faces itself
|
||||
* and apply this permutation to all face layers
|
||||
*/
|
||||
if (event == 5) {
|
||||
/* Random */
|
||||
for(i=0; i<me->totface; i++) {
|
||||
face_sort_floats[i] = BLI_frand();
|
||||
}
|
||||
qsort(index, me->totface, sizeof(int), float_sort);
|
||||
} else {
|
||||
MFace *mf;
|
||||
float vec[3];
|
||||
float mat[4][4];
|
||||
float cur[3];
|
||||
|
||||
if (event == 1)
|
||||
mul_m4_m4m4(mat, OBACT->obmat, rv3d->viewmat); /* apply the view matrix to the object matrix */
|
||||
else if (event == 2) { /* sort from cursor */
|
||||
if( v3d && v3d->localvd ) {
|
||||
VECCOPY(cur, v3d->cursor);
|
||||
} else {
|
||||
VECCOPY(cur, scene->cursor);
|
||||
}
|
||||
invert_m4_m4(mat, OBACT->obmat);
|
||||
mul_m4_v3(mat, cur);
|
||||
}
|
||||
|
||||
mf= me->mface;
|
||||
|
||||
for(i=0; i<me->totface; i++, mf++) {
|
||||
if (event==3) {
|
||||
face_sort_floats[i] = ((float)mf->mat_nr)*reverse;
|
||||
} else if (event==4) {
|
||||
/*selected first*/
|
||||
if (mf->flag & ME_FACE_SEL)
|
||||
face_sort_floats[i] = 0.0;
|
||||
else
|
||||
face_sort_floats[i] = reverse;
|
||||
} else {
|
||||
/* find the faces center */
|
||||
add_v3_v3v3(vec, (me->mvert+mf->v1)->co, (me->mvert+mf->v2)->co);
|
||||
if (mf->v4) {
|
||||
add_v3_v3(vec, (me->mvert+mf->v3)->co);
|
||||
add_v3_v3(vec, (me->mvert+mf->v4)->co);
|
||||
mul_v3_fl(vec, 0.25f);
|
||||
} else {
|
||||
add_v3_v3(vec, (me->mvert+mf->v3)->co);
|
||||
mul_v3_fl(vec, 1.0f/3.0f);
|
||||
} /* done */
|
||||
|
||||
if (event == 1) { /* sort on view axis */
|
||||
mul_m4_v3(mat, vec);
|
||||
face_sort_floats[i] = vec[2] * reverse;
|
||||
} else if(event == 2) { /* distance from cursor*/
|
||||
face_sort_floats[i] = len_v3v3(cur, vec) * reverse; /* back to front */
|
||||
}
|
||||
}
|
||||
}
|
||||
qsort(index, me->totface, sizeof(int), float_sort);
|
||||
}
|
||||
|
||||
MEM_freeN(face_sort_floats);
|
||||
for(i = 0; i < me->fdata.totlayer; i++) {
|
||||
layer = &me->fdata.layers[i];
|
||||
permutate(layer->data, me->totface, CustomData_sizeof(layer->type), index);
|
||||
}
|
||||
|
||||
MEM_freeN(index);
|
||||
DAG_id_flush_update(ob->data, OB_RECALC_DATA);
|
||||
|
||||
/* Return to editmode. */
|
||||
ED_object_enter_editmode(C, 0);
|
||||
}
|
||||
|
||||
void MESH_OT_sort_faces(wmOperatorType *ot)
|
||||
{
|
||||
static EnumPropertyItem type_items[]= {
|
||||
{ 1, "VIEW_AXIS", 0, "View Axis", "" },
|
||||
{ 2, "CURSOR_DISTANCE", 0, "Cursor Distance", "" },
|
||||
{ 3, "MATERIAL", 0, "Material", "" },
|
||||
{ 4, "SELECTION", 0, "Selection", "" },
|
||||
{ 5, "RANDOMIZE", 0, "Randomize", "" },
|
||||
{ 0, NULL, 0, NULL, NULL }};
|
||||
|
||||
/* identifiers */
|
||||
ot->name= "Sort Faces"; // XXX (Ctrl to reverse)%t|
|
||||
ot->description= "The faces of the active Mesh Object are sorted, based on the current view.";
|
||||
ot->idname= "MESH_OT_sort_faces";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= sort_faces_exec;
|
||||
ot->poll= ED_operator_editmesh;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
ot->prop= RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
|
||||
}
|
||||
|
||||
/********************** Quad/Tri Operators *************************/
|
||||
|
||||
static int quads_convert_to_tris_exec(bContext *C, wmOperator *op)
|
||||
|
||||
@@ -241,6 +241,7 @@ void MESH_OT_rip(struct wmOperatorType *ot);
|
||||
|
||||
void MESH_OT_shape_propagate_to_all(struct wmOperatorType *ot);
|
||||
void MESH_OT_blend_from_shape(struct wmOperatorType *ot);
|
||||
void MESH_OT_sort_faces(struct wmOperatorType *ot);
|
||||
|
||||
/* ******************* mesh_data.c */
|
||||
|
||||
|
||||
@@ -113,6 +113,7 @@ void ED_operatortypes_mesh(void)
|
||||
WM_operatortype_append(MESH_OT_edge_flip);
|
||||
WM_operatortype_append(MESH_OT_faces_shade_smooth);
|
||||
WM_operatortype_append(MESH_OT_faces_shade_flat);
|
||||
WM_operatortype_append(MESH_OT_sort_faces);
|
||||
|
||||
WM_operatortype_append(MESH_OT_delete);
|
||||
|
||||
@@ -273,6 +274,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
|
||||
|
||||
WM_keymap_add_item(keymap, "MESH_OT_fill", FKEY, KM_PRESS, KM_ALT, 0);
|
||||
WM_keymap_add_item(keymap, "MESH_OT_beautify_fill", FKEY, KM_PRESS, KM_SHIFT|KM_ALT, 0);
|
||||
WM_keymap_add_item(keymap, "MESH_OT_sort_faces", FKEY, KM_PRESS, KM_ALT|KM_CTRL, 0);
|
||||
WM_keymap_add_item(keymap, "MESH_OT_quads_convert_to_tris", TKEY, KM_PRESS, KM_CTRL, 0);
|
||||
WM_keymap_add_item(keymap, "MESH_OT_tris_convert_to_quads", JKEY, KM_PRESS, KM_ALT, 0);
|
||||
WM_keymap_add_item(keymap, "MESH_OT_edge_flip", FKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
|
||||
|
||||
@@ -601,153 +601,6 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
/* ********************** SORT FACES ******************* */
|
||||
|
||||
static void permutate(void *list, int num, int size, int *index)
|
||||
{
|
||||
void *buf;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
len = num * size;
|
||||
|
||||
buf = MEM_mallocN(len, "permutate");
|
||||
memcpy(buf, list, len);
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
memcpy((char *)list + (i * size), (char *)buf + (index[i] * size), size);
|
||||
}
|
||||
MEM_freeN(buf);
|
||||
}
|
||||
|
||||
/* sort faces on view axis */
|
||||
static float *face_sort_floats;
|
||||
static int float_sort(const void *v1, const void *v2)
|
||||
{
|
||||
float x1, x2;
|
||||
|
||||
x1 = face_sort_floats[((int *) v1)[0]];
|
||||
x2 = face_sort_floats[((int *) v2)[0]];
|
||||
|
||||
if( x1 > x2 ) return 1;
|
||||
else if( x1 < x2 ) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void sort_faces(Scene *scene, View3D *v3d)
|
||||
{
|
||||
RegionView3D *rv3d= NULL; // get from context
|
||||
Object *ob= OBACT;
|
||||
Mesh *me;
|
||||
CustomDataLayer *layer;
|
||||
int i, *index;
|
||||
short event;
|
||||
float reverse = 1;
|
||||
int ctrl= 0; // XXX
|
||||
|
||||
if(!ob) return;
|
||||
if(scene->obedit) return;
|
||||
if(ob->type!=OB_MESH) return;
|
||||
if (!v3d) return;
|
||||
|
||||
me= ob->data;
|
||||
if(me->totface==0) return;
|
||||
|
||||
event = pupmenu(
|
||||
"Sort Faces (Ctrl to reverse)%t|"
|
||||
"View Axis%x1|"
|
||||
"Cursor Distance%x2|"
|
||||
"Material%x3|"
|
||||
"Selection%x4|"
|
||||
"Randomize%x5");
|
||||
|
||||
if (event==-1) return;
|
||||
|
||||
if(ctrl)
|
||||
reverse = -1;
|
||||
|
||||
/* create index list */
|
||||
index = (int *) MEM_mallocN(sizeof(int) * me->totface, "sort faces");
|
||||
for (i = 0; i < me->totface; i++) {
|
||||
index[i] = i;
|
||||
}
|
||||
|
||||
face_sort_floats = (float *) MEM_mallocN(sizeof(float) * me->totface, "sort faces float");
|
||||
|
||||
/* sort index list instead of faces itself
|
||||
and apply this permutation to all face layers */
|
||||
|
||||
if (event == 5) {
|
||||
/* Random */
|
||||
for(i=0; i<me->totface; i++) {
|
||||
face_sort_floats[i] = BLI_frand();
|
||||
}
|
||||
qsort(index, me->totface, sizeof(int), float_sort);
|
||||
} else {
|
||||
MFace *mf;
|
||||
float vec[3];
|
||||
float mat[4][4];
|
||||
float cur[3];
|
||||
|
||||
if (event == 1)
|
||||
mul_m4_m4m4(mat, OBACT->obmat, rv3d->viewmat); /* apply the view matrix to the object matrix */
|
||||
else if (event == 2) { /* sort from cursor */
|
||||
if( v3d && v3d->localvd ) {
|
||||
VECCOPY(cur, v3d->cursor);
|
||||
} else {
|
||||
VECCOPY(cur, scene->cursor);
|
||||
}
|
||||
invert_m4_m4(mat, OBACT->obmat);
|
||||
mul_m4_v3(mat, cur);
|
||||
}
|
||||
|
||||
mf= me->mface;
|
||||
for(i=0; i<me->totface; i++, mf++) {
|
||||
|
||||
if (event==3) {
|
||||
face_sort_floats[i] = ((float)mf->mat_nr)*reverse;
|
||||
} else if (event==4) {
|
||||
/*selected first*/
|
||||
if (mf->flag & ME_FACE_SEL) face_sort_floats[i] = 0.0;
|
||||
else face_sort_floats[i] = reverse;
|
||||
} else {
|
||||
/* find the faces center */
|
||||
add_v3_v3v3(vec, (me->mvert+mf->v1)->co, (me->mvert+mf->v2)->co);
|
||||
if (mf->v4) {
|
||||
add_v3_v3(vec, (me->mvert+mf->v3)->co);
|
||||
add_v3_v3(vec, (me->mvert+mf->v4)->co);
|
||||
mul_v3_fl(vec, 0.25f);
|
||||
} else {
|
||||
add_v3_v3(vec, (me->mvert+mf->v3)->co);
|
||||
mul_v3_fl(vec, 1.0f/3.0f);
|
||||
} /* done */
|
||||
|
||||
if (event == 1) { /* sort on view axis */
|
||||
mul_m4_v3(mat, vec);
|
||||
face_sort_floats[i] = vec[2] * reverse;
|
||||
} else if(event == 2) { /* distance from cursor*/
|
||||
face_sort_floats[i] = len_v3v3(cur, vec) * reverse; /* back to front */
|
||||
}
|
||||
}
|
||||
}
|
||||
qsort(index, me->totface, sizeof(int), float_sort);
|
||||
}
|
||||
|
||||
MEM_freeN(face_sort_floats);
|
||||
|
||||
for(i = 0; i < me->fdata.totlayer; i++) {
|
||||
layer = &me->fdata.layers[i];
|
||||
permutate(layer->data, me->totface, CustomData_sizeof(layer->type), index);
|
||||
}
|
||||
|
||||
MEM_freeN(index);
|
||||
|
||||
DAG_id_flush_update(ob->data, OB_RECALC_DATA);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ********************* MESH VERTEX OCTREE LOOKUP ************* */
|
||||
|
||||
/* important note; this is unfinished, needs better API for editmode, and custom threshold */
|
||||
|
||||
Reference in New Issue
Block a user