diff options
Diffstat (limited to 'source/blender/editors')
74 files changed, 10694 insertions, 7373 deletions
diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt index d13d7ce2ff2..5433e317bd1 100644 --- a/source/blender/editors/CMakeLists.txt +++ b/source/blender/editors/CMakeLists.txt @@ -27,65 +27,61 @@ FILE(GLOB SRC */*.c) SET(INC ../windowmanager - ../editors/include - ../../../intern/guardedalloc ../../../intern/memutil - ../blenlib ../makesdna ../makesrna ../blenkernel - ../include ../imbuf ../render/extern/include - ../../../intern/bsp/extern - ../../../intern/decimation/extern ../blenloader ../python - ../../kernel/gen_system ../readstreamglue - ../../../intern/elbeem/extern - ../../../intern/ghost ../../../intern/opennl/extern ../../../extern/glew/include ../../../intern/smoke/extern - ../../../intern/audaspace/intern - ../nodes - ../gpu - ../blenfont + ../editors/include + ../../../intern/guardedalloc ../../../intern/memutil + ../blenlib ../makesdna ../makesrna ../blenkernel + ../include ../imbuf ../render/extern/include + ../../../intern/bsp/extern ../radiosity/extern/include + ../../../intern/decimation/extern ../blenloader ../python + ../../kernel/gen_system ../../../intern/SoundSystem ../readstreamglue + ../quicktime ../../../intern/elbeem/extern + ../../../intern/ghost ../../../intern/opennl/extern ../../../extern/glew/include ../../../intern/smoke/extern + ../nodes ../bmesh + ../gpu + ../blenfont + ${SDL_INC} ../ikplugin ) -IF(WITH_GAMEENGINE) - ADD_DEFINITIONS(-DGAMEBLENDER) -ENDIF(WITH_GAMEENGINE) - IF(WITH_INTERNATIONAL) - ADD_DEFINITIONS(-DINTERNATIONAL) + ADD_DEFINITIONS(-DINTERNATIONAL) ENDIF(WITH_INTERNATIONAL) IF(WITH_OPENEXR) - ADD_DEFINITIONS(-DWITH_OPENEXR) + ADD_DEFINITIONS(-DWITH_OPENEXR) ENDIF(WITH_OPENEXR) IF(WITH_OPENJPEG) - ADD_DEFINITIONS(-DWITH_OPENJPEG) + ADD_DEFINITIONS(-DWITH_OPENJPEG) ENDIF(WITH_OPENJPEG) IF(WITH_QUICKTIME) - SET(INC ${INC} ../quicktime ${QUICKTIME_INC}) - ADD_DEFINITIONS(-DWITH_QUICKTIME) + SET(INC ${INC} ${QUICKTIME_INC}) + ADD_DEFINITIONS(-DWITH_QUICKTIME) ENDIF(WITH_QUICKTIME) IF(WITH_FFMPEG) - SET(INC ${INC} ${FFMPEG_INC}) - ADD_DEFINITIONS(-DWITH_FFMPEG) + SET(INC ${INC} ${FFMPEG_INC}) + ADD_DEFINITIONS(-DWITH_FFMPEG) ENDIF(WITH_FFMPEG) IF(NOT WITH_ELBEEM) - ADD_DEFINITIONS(-DDISABLE_ELBEEM) + ADD_DEFINITIONS(-DDISABLE_ELBEEM) ENDIF(NOT WITH_ELBEEM) IF(WITH_PYTHON) - SET(INC ${INC} ${PYTHON_INC}) + SET(INC ${INC} ${PYTHON_INC}) ELSE(WITH_PYTHON) - ADD_DEFINITIONS(-DDISABLE_PYTHON) + ADD_DEFINITIONS(-DDISABLE_PYTHON) ENDIF(WITH_PYTHON) IF(WIN32) - SET(INC ${INC} ${PTHREADS_INC}) + SET(INC ${INC} ${PTHREADS_INC}) ENDIF(WIN32) # TODO buildinfo IF(BF_BUILDINFO) - ADD_DEFINITIONS(-DNAN_BUILDINFO) + ADD_DEFINITIONS(-DNAN_BUILDINFO) ENDIF(BF_BUILDINFO) BLENDERLIB_NOLIST(bf_editors "${SRC}" "${INC}") diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 82843a49851..160f505c3f5 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -1116,8 +1116,8 @@ static void meshdeform_ray_tree_create(MeshDeformBind *mdb) MESHDEFORM_BIND= mdb; - mface= mdb->cagedm->getFaceArray(mdb->cagedm); - totface= mdb->cagedm->getNumFaces(mdb->cagedm); + mface= mdb->cagedm->getTessFaceArray(mdb->cagedm); + totface= mdb->cagedm->getNumTessFaces(mdb->cagedm); mdb->raytree= RE_ray_tree_create(64, totface, min, max, meshdeform_ray_coords_func, meshdeform_ray_check_func); @@ -1143,8 +1143,8 @@ static int meshdeform_intersect(MeshDeformBind *mdb, Isect *isec) isec->labda= 1e10; - mface= mdb->cagedm->getFaceArray(mdb->cagedm); - totface= mdb->cagedm->getNumFaces(mdb->cagedm); + mface= mdb->cagedm->getTessFaceArray(mdb->cagedm); + totface= mdb->cagedm->getNumTessFaces(mdb->cagedm); VECADDFAC( end, isec->start, isec->vec, isec->labda ); diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c index 132d9edf8d0..2a012437b42 100644 --- a/source/blender/editors/armature/reeb.c +++ b/source/blender/editors/armature/reeb.c @@ -64,6 +64,7 @@ #include "BKE_global.h" #include "BKE_utildefines.h" #include "BKE_customdata.h" +#include "BKE_mesh.h" //#include "blendef.h" @@ -3387,7 +3388,7 @@ ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C) { Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); - EditMesh *em =( (Mesh*)obedit->data)->edit_mesh; + EditMesh *em =BKE_mesh_get_editmesh(((Mesh*)obedit->data)); EdgeIndex indexed_edges; VertexData *data; ReebGraph *rg = NULL; @@ -3483,6 +3484,12 @@ ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C) MEM_freeN(data); + /*no need to load the editmesh back into the object, just + free it (avoids ngon conversion issues too going back the + other way)*/ + free_editMesh(em); + MEM_freeN(em); + return rg; } diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 50411c9d998..d4b695e1b7f 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -36,7 +36,6 @@ struct EditVert; struct EditEdge; struct EditFace; struct bContext; -struct wmOperator; struct wmWindowManager; struct wmKeyConfig; struct ReportList; @@ -51,37 +50,105 @@ struct MCol; struct UvVertMap; struct UvMapVert; struct CustomData; +struct BMEditSelection; +struct BMesh; +struct BMVert; +struct BMEdge; +struct BMFace; +struct UvVertMap; +struct UvMapVert; struct Material; struct Object; -#define EM_FGON_DRAW 1 // face flag -#define EM_FGON 2 // edge and face flag both +// edge and face flag both +#define EM_FGON 2 +// face flag +#define EM_FGON_DRAW 1 /* editbutflag */ -#define B_CLOCKWISE 1 -#define B_KEEPORIG 2 -#define B_BEAUTY 4 -#define B_SMOOTH 8 -#define B_BEAUTY_SHORT 0x10 -#define B_AUTOFGON 0x20 -#define B_KNIFE 0x80 +#define B_CLOCKWISE 1 +#define B_KEEPORIG 2 +#define B_BEAUTY 4 +#define B_SMOOTH 8 +#define B_BEAUTY_SHORT 16 +#define B_AUTOFGON 32 +#define B_KNIFE 0x80 #define B_PERCENTSUBD 0x40 //#define B_MESH_X_MIRROR 0x100 // deprecated, use mesh #define B_JOINTRIA_UV 0x200 #define B_JOINTRIA_VCOL 0X400 #define B_JOINTRIA_SHARP 0X800 #define B_JOINTRIA_MAT 0X1000 -#define B_FRACTAL 0x2000 -#define B_SPHERE 0x4000 +#define B_FRACTAL 0x2000 +#define B_SPHERE 0x4000 + +/* bmeshutils.c */ + +void EDBM_RecalcNormals(struct BMEditMesh *em); + +void EDBM_MakeEditBMesh(struct ToolSettings *ts, struct Scene *scene, struct Object *ob); +void EDBM_FreeEditBMesh(struct BMEditMesh *tm); +void EDBM_LoadEditBMesh(struct Scene *scene, struct Object *ob); + +void EDBM_init_index_arrays(struct BMEditMesh *tm, int forvert, int foredge, int forface); +void EDBM_free_index_arrays(struct BMEditMesh *tm); +struct BMVert *EDBM_get_vert_for_index(struct BMEditMesh *tm, int index); +struct BMEdge *EDBM_get_edge_for_index(struct BMEditMesh *tm, int index); +struct BMFace *EDBM_get_face_for_index(struct BMEditMesh *tm, int index); +struct BMFace *EDBM_get_actFace(struct BMEditMesh *em, int sloppy); + +/*flushes based on the current select mode. if in vertex select mode, + verts select/deselect edges and faces, if in edge select mode, + edges select/deselect faces and vertices, and in face select mode faces select/deselect + edges and vertices.*/ +void EDBM_selectmode_flush(struct BMEditMesh *em); + +int EDBM_get_actSelection(struct BMEditMesh *em, struct BMEditSelection *ese); + +/*exactly the same as EDBM_selectmode_flush, but you pass in the selectmode + instead of using the current one*/ +void EDBM_select_flush(struct BMEditMesh *em, int selectmode); +void EDBM_deselect_flush(struct BMEditMesh *em); + +void EDBM_selectmode_set(struct BMEditMesh *em); +void EDBM_convertsel(struct BMEditMesh *em, short oldmode, short selectmode); + +void EDBM_editselection_center(struct BMEditMesh *em, float *center, struct BMEditSelection *ese); +void EDBM_editselection_plane(struct BMEditMesh *em, float *plane, struct BMEditSelection *ese); +void EDBM_editselection_normal(float *normal, struct BMEditSelection *ese); +int EDBM_vertColorCheck(struct BMEditMesh *em); + +void EDBM_pin_mesh(struct BMEditMesh *em, int swap); +void EDBM_unpin_mesh(struct BMEditMesh *em, int swap); + +void EDBM_hide_mesh(struct BMEditMesh *em, int swap); +void EDBM_reveal_mesh(struct BMEditMesh *em); + +int EDBM_check_backbuf(unsigned int index); +int EDBM_mask_init_backbuf_border(struct ViewContext *vc, short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax); +void EDBM_free_backbuf(void); +int EDBM_init_backbuf_border(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax); +int EDBM_init_backbuf_circle(struct ViewContext *vc, short xs, short ys, short rads); + +void EDBM_select_swap(struct BMEditMesh *em); /* exported for UV */ +void EDBM_set_actFace(struct BMEditMesh *em, struct BMFace *efa); + +int EDBM_texFaceCheck(struct BMEditMesh *em); +struct MTexPoly *EDBM_get_active_mtexpoly(struct BMEditMesh *em, struct BMFace **act_efa, int sloppy); + +void EDBM_free_uv_vert_map(struct UvVertMap *vmap); +struct UvMapVert *EDBM_get_uv_map_vert(struct UvVertMap *vmap, unsigned int v); +struct UvVertMap *EDBM_make_uv_vert_map(struct BMEditMesh *em, int selected, int do_face_idx_array, float *limit); + +void EDBM_toggle_select_all(struct BMEditMesh *em); +void EDBM_set_flag_all(struct BMEditMesh *em, int flag); /* meshtools.c */ -intptr_t mesh_octree_table(struct Object *ob, struct EditMesh *em, float *co, char mode); -struct EditVert *editmesh_get_x_mirror_vert(struct Object *ob, struct EditMesh *em, float *co); +intptr_t mesh_octree_table(struct Object *ob, struct BMEditMesh *em, float *co, char mode); +struct BMVert *editmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em, float *co); int mesh_get_x_mirror_vert(struct Object *ob, int index); -int *mesh_get_x_mirror_faces(struct Object *ob, struct EditMesh *em); - -int join_mesh_exec(struct bContext *C, struct wmOperator *op); +int *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em); /* mesh_ops.c */ void ED_operatortypes_mesh(void); @@ -94,8 +161,8 @@ void ED_keymap_mesh(struct wmKeyConfig *keyconf); void ED_spacetypes_init(void); void ED_keymap_mesh(struct wmKeyConfig *keyconf); -void make_editMesh(struct Scene *scene, struct Object *ob); -void load_editMesh(struct Scene *scene, struct Object *ob); +struct EditMesh *make_editMesh(struct Scene *scene, struct Object *ob); +void load_editMesh(struct Scene *scene, struct Object *ob, struct EditMesh *em); void remake_editMesh(struct Scene *scene, struct Object *ob); void free_editMesh(struct EditMesh *em); @@ -117,6 +184,7 @@ void undo_push_mesh(struct bContext *C, char *name); struct EditFace *EM_get_actFace(struct EditMesh *em, int sloppy); void EM_set_actFace(struct EditMesh *em, struct EditFace *efa); float EM_face_area(struct EditFace *efa); +void EM_add_data_layer(struct EditMesh *em, struct CustomData *data, int type); void EM_select_edge(struct EditEdge *eed, int sel); void EM_select_face(struct EditFace *efa, int sel); @@ -141,11 +209,8 @@ struct UvVertMap *EM_make_uv_vert_map(struct EditMesh *em, int selected, int do_ struct UvMapVert *EM_get_uv_map_vert(struct UvVertMap *vmap, unsigned int v); void EM_free_uv_vert_map(struct UvVertMap *vmap); -void EM_add_data_layer(struct EditMesh *em, struct CustomData *data, int type); -void EM_free_data_layer(struct EditMesh *em, struct CustomData *data, int type); - /* editmesh_mods.c */ -extern unsigned int em_vertoffs, em_solidoffs, em_wireoffs; +extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs; void mouse_mesh(struct bContext *C, short mval[2], short extend); int EM_check_backbuf(unsigned int index); @@ -157,9 +222,6 @@ int EM_init_backbuf_circle(struct ViewContext *vc, short xs, short ys, short r void EM_hide_mesh(struct EditMesh *em, int swap); void EM_reveal_mesh(struct EditMesh *em); -void EM_select_by_material(struct EditMesh *em, int index); -void EM_deselect_by_material(struct EditMesh *em, int index); - void EM_automerge(struct Scene *scene, struct Object *obedit, int update); /* editface.c */ @@ -183,6 +245,20 @@ float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int ver struct MDeformWeight *ED_vgroup_weight_verify(struct MDeformVert *dv, int defgroup); struct MDeformWeight *ED_vgroup_weight_get(struct MDeformVert *dv, int defgroup); +/** + * findnearestvert + * + * dist (in/out): minimal distance to the nearest and at the end, actual distance + * sel: selection bias + * if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts + * if 0, unselected vertice are given the bias + * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased + */ + +struct BMVert *EDBM_findnearestvert(struct ViewContext *vc, int *dist, short sel, short strict); +struct BMEdge *EDBM_findnearestedge(struct ViewContext *vc, int *dist); +struct BMFace *EDBM_findnearestface(struct ViewContext *vc, int *dist); + /*needed by edge slide*/ struct EditVert *editedge_getOtherVert(struct EditEdge *eed, struct EditVert *eve); struct EditVert *editedge_getSharedVert(struct EditEdge *eed, struct EditEdge *eed2); @@ -205,4 +281,3 @@ int ED_mesh_color_add(struct bContext *C, struct Scene *scene, struct Object *ob int ED_mesh_color_remove(struct bContext *C, struct Object *ob, struct Mesh *me); #endif /* ED_MESH_H */ - diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index 8823437cf79..bf9b95d49d8 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -47,10 +47,10 @@ int ED_uvedit_minmax(struct Scene *scene, struct Image *ima, struct Object *obed int ED_uvedit_test_silent(struct Object *obedit); int ED_uvedit_test(struct Object *obedit); -int uvedit_face_visible(struct Scene *scene, struct Image *ima, struct EditFace *efa, struct MTFace *tf); -int uvedit_face_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf); -int uvedit_edge_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i); -int uvedit_uv_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i); +int uvedit_face_visible(struct Scene *scene, struct Image *ima, struct BMFace *efa, struct MTexPoly *tf); +int uvedit_face_selected(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa); +int uvedit_edge_selected(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l); +int uvedit_uv_selected(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l); int ED_uvedit_nearest_uv(struct Scene *scene, struct Object *obedit, struct Image *ima, float co[2], float uv[2]); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 2752402fb66..307dbd74872 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -37,9 +37,9 @@ struct bglMats; struct BPoint; struct Nurb; struct BezTriple; -struct EditVert; -struct EditEdge; -struct EditFace; +struct BMVert; +struct BMEdge; +struct BMFace; struct ImBuf; struct Scene; struct bContext; @@ -52,7 +52,7 @@ typedef struct ViewContext { struct ARegion *ar; struct View3D *v3d; struct RegionView3D *rv3d; - struct EditMesh *em; + struct BMEditMesh *em; short mval[2]; } ViewContext; @@ -97,9 +97,9 @@ void view3d_get_object_project_mat(struct RegionView3D *v3d, struct Object *ob, void view3d_project_float(struct ARegion *a, float *vec, float *adr, float mat[4][4]); /* drawobject.c itterators */ -void mesh_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct EditVert *eve, int x, int y, int index), void *userData, int clipVerts); -void mesh_foreachScreenEdge(struct ViewContext *vc, void (*func)(void *userData, struct EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts); -void mesh_foreachScreenFace(struct ViewContext *vc, void (*func)(void *userData, struct EditFace *efa, int x, int y, int index), void *userData); +void mesh_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct BMVert *eve, int x, int y, int index), void *userData, int clipVerts); +void mesh_foreachScreenEdge(struct ViewContext *vc, void (*func)(void *userData, struct BMEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts); +void mesh_foreachScreenFace(struct ViewContext *vc, void (*func)(void *userData, struct BMFace *efa, int x, int y, int index), void *userData); void nurbs_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct Nurb *nu, struct BPoint *bp, struct BezTriple *bezt, int beztindex, int x, int y), void *userData); void lattice_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct BPoint *bp, int x, int y), void *userData); diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 1ae3634c73b..6e7814ad0f8 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -202,6 +202,9 @@ enum { TH_DOPESHEET_CHANNELOB, TH_DOPESHEET_CHANNELSUBOB, + + TH_PIN, + TH_PIN_OPAC, }; /* XXX WARNING: previous is saved in file, so do not change order! */ diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 26a50cc3c24..5e148717963 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -355,6 +355,10 @@ char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) case TH_DOPESHEET_CHANNELSUBOB: cp= ts->ds_subchannel; break; + case TH_PIN: + cp= ts->pin; break; + case TH_PIN_OPAC: + cp= &ts->pin_opac; break; } } @@ -475,6 +479,9 @@ void ui_theme_init_userdef(void) SETCOL(btheme->tv3d.bone_solid, 200, 200, 200, 255); SETCOL(btheme->tv3d.bone_pose, 80, 200, 255, 80); // alpha 80 is not meant editable, used for wire+action draw + + SETCOL(btheme->tv3d.pin, 115, 171, 209, 255); + btheme->tv3d.pin_opac = 40; /* space buttons */ diff --git a/source/blender/editors/mesh/SConscript b/source/blender/editors/mesh/SConscript index 00391b3474a..ac46ee157cc 100644 --- a/source/blender/editors/mesh/SConscript +++ b/source/blender/editors/mesh/SConscript @@ -7,6 +7,7 @@ incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' #/intern/guardedalloc ../../gpu' incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern' +incs += ' ../../bmesh ' if env['OURPLATFORM'] == 'linux2': cflags='-pthread' diff --git a/source/blender/editors/mesh/bmesh_select.c b/source/blender/editors/mesh/bmesh_select.c new file mode 100644 index 00000000000..3e1d5034328 --- /dev/null +++ b/source/blender/editors/mesh/bmesh_select.c @@ -0,0 +1,1772 @@ +/** + * $Id: + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/* + +BMEditMesh_mods.c, UI level access, no geometry changes + +*/ + +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_mesh_types.h" +#include "DNA_material_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_texture_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_view3d_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_rand.h" +#include "BLI_array.h" + +#include "BKE_context.h" +#include "BKE_displist.h" +#include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" +#include "BKE_customdata.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_material.h" +#include "BKE_texture.h" +#include "BKE_utildefines.h" +#include "BKE_report.h" +#include "BKE_tessmesh.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +#include "RE_render_ext.h" /* externtex */ + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "ED_mesh.h" +#include "ED_screen.h" +#include "ED_view3d.h" +#include "bmesh.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "UI_resources.h" + +#include "mesh_intern.h" + +#include "BLO_sys_types.h" // for intptr_t support + +/* XXX */ +static void waitcursor() {} +static int pupmenu() {return 0;} + +/* ****************************** MIRROR **************** */ + +void EDBM_select_mirrored(Object *obedit, BMEditMesh *em) +{ +#if 0 //BMESH_TODO + if(em->selectmode & SCE_SELECT_VERTEX) { + BMVert *eve, *v1; + + for(eve= em->verts.first; eve; eve= eve->next) { + if(eve->f & SELECT) { + v1= BMEditMesh_get_x_mirror_vert(obedit, em, eve->co); + if(v1) { + eve->f &= ~SELECT; + v1->f |= SELECT; + } + } + } + } +#endif +} + +void EDBM_automerge(Scene *scene, Object *obedit, int update) +{ + BMEditMesh *em; + int len; + + if ((scene->toolsettings->automerge) && + (obedit && obedit->type==OB_MESH) && + (((Mesh*)obedit->data)->mr==NULL)) + { + em = ((Mesh*)obedit->data)->edit_btmesh; + if (!em) + return; + + BMO_CallOpf(em->bm, "automerge verts=%hv dist=%f", BM_SELECT, scene->toolsettings->doublimit); + if (update) { + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + } + } +} + +/* ****************************** SELECTION ROUTINES **************** */ + +unsigned int bm_solidoffs=0, bm_wireoffs=0, bm_vertoffs=0; /* set in drawobject.c ... for colorindices */ + +/* facilities for border select and circle select */ +static char *selbuf= NULL; + +/* opengl doesn't support concave... */ +static void draw_triangulated(short mcords[][2], short tot) +{ + ListBase lb={NULL, NULL}; + DispList *dl; + float *fp; + int a; + + /* make displist */ + dl= MEM_callocN(sizeof(DispList), "poly disp"); + dl->type= DL_POLY; + dl->parts= 1; + dl->nr= tot; + dl->verts= fp= MEM_callocN(tot*3*sizeof(float), "poly verts"); + BLI_addtail(&lb, dl); + + for(a=0; a<tot; a++, fp+=3) { + fp[0]= (float)mcords[a][0]; + fp[1]= (float)mcords[a][1]; + } + + /* do the fill */ + filldisplist(&lb, &lb); + + /* do the draw */ + dl= lb.first; /* filldisplist adds in head of list */ + if(dl->type==DL_INDEX3) { + int *index; + + a= dl->parts; + fp= dl->verts; + index= dl->index; + glBegin(GL_TRIANGLES); + while(a--) { + glVertex3fv(fp+3*index[0]); + glVertex3fv(fp+3*index[1]); + glVertex3fv(fp+3*index[2]); + index+= 3; + } + glEnd(); + } + + freedisplist(&lb); +} + + +/* reads rect, and builds selection array for quick lookup */ +/* returns if all is OK */ +int EDBM_init_backbuf_border(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) +{ + struct ImBuf *buf; + unsigned int *dr; + int a; + + if(vc->obedit==NULL || vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0; + + buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); + if(buf==NULL) return 0; + if(bm_vertoffs==0) return 0; + + dr = buf->rect; + + /* build selection lookup */ + selbuf= MEM_callocN(bm_vertoffs+1, "selbuf"); + + a= (xmax-xmin+1)*(ymax-ymin+1); + while(a--) { + if(*dr>0 && *dr<=bm_vertoffs) + selbuf[*dr]= 1; + dr++; + } + IMB_freeImBuf(buf); + return 1; +} + +int EDBM_check_backbuf(unsigned int index) +{ + if(selbuf==NULL) return 1; + if(index>0 && index<=bm_vertoffs) + return selbuf[index]; + return 0; +} + +void EDBM_free_backbuf(void) +{ + if(selbuf) MEM_freeN(selbuf); + selbuf= NULL; +} + +/* mcords is a polygon mask + - grab backbuffer, + - draw with black in backbuffer, + - grab again and compare + returns 'OK' +*/ +int EDBM_mask_init_backbuf_border(ViewContext *vc, short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax) +{ + unsigned int *dr, *drm; + struct ImBuf *buf, *bufmask; + int a; + + /* method in use for face selecting too */ + if(vc->obedit==NULL) { + if(paint_facesel_test(vc->obact)); + else return 0; + } + else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0; + + buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); + if(buf==NULL) return 0; + if(bm_vertoffs==0) return 0; + + dr = buf->rect; + + /* draw the mask */ + glDisable(GL_DEPTH_TEST); + + glColor3ub(0, 0, 0); + + /* yah, opengl doesn't do concave... tsk! */ + ED_region_pixelspace(vc->ar); + draw_triangulated(mcords, tot); + + glBegin(GL_LINE_LOOP); /* for zero sized masks, lines */ + for(a=0; a<tot; a++) glVertex2s(mcords[a][0], mcords[a][1]); + glEnd(); + + glFinish(); /* to be sure readpixels sees mask */ + + /* grab mask */ + bufmask= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); + drm = bufmask->rect; + if(bufmask==NULL) return 0; /* only when mem alloc fails, go crash somewhere else! */ + + /* build selection lookup */ + selbuf= MEM_callocN(bm_vertoffs+1, "selbuf"); + + a= (xmax-xmin+1)*(ymax-ymin+1); + while(a--) { + if(*dr>0 && *dr<=bm_vertoffs && *drm==0) selbuf[*dr]= 1; + dr++; drm++; + } + IMB_freeImBuf(buf); + IMB_freeImBuf(bufmask); + return 1; + +} + +/* circle shaped sample area */ +int EDBM_init_backbuf_circle(ViewContext *vc, short xs, short ys, short rads) +{ + struct ImBuf *buf; + unsigned int *dr; + short xmin, ymin, xmax, ymax, xc, yc; + int radsq; + + /* method in use for face selecting too */ + if(vc->obedit==NULL) { + if(paint_facesel_test(vc->obact)); + else return 0; + } + else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0; + + xmin= xs-rads; xmax= xs+rads; + ymin= ys-rads; ymax= ys+rads; + buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); + if(bm_vertoffs==0) return 0; + if(buf==NULL) return 0; + + dr = buf->rect; + + /* build selection lookup */ + selbuf= MEM_callocN(bm_vertoffs+1, "selbuf"); + radsq= rads*rads; + for(yc= -rads; yc<=rads; yc++) { + for(xc= -rads; xc<=rads; xc++, dr++) { + if(xc*xc + yc*yc < radsq) { + if(*dr>0 && *dr<=bm_vertoffs) selbuf[*dr]= 1; + } + } + } + + IMB_freeImBuf(buf); + return 1; + +} + +static void findnearestvert__doClosest(void *userData, BMVert *eve, int x, int y, int index) +{ + struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; BMVert *closest; } *data = userData; + + if (data->pass==0) { + if (index<=data->lastIndex) + return; + } else { + if (index>data->lastIndex) + return; + } + + if (data->dist>3) { + int temp = abs(data->mval[0] - x) + abs(data->mval[1]- y); + if (BM_TestHFlag(eve, BM_SELECT) == data->select) { + if (data->strict == 1) + return; + else + temp += 5; + } + + if (temp<data->dist) { + data->dist = temp; + data->closest = eve; + data->closestIndex = index; + } + } +} + + + + +static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int index) +{ + BMEditMesh *em= (BMEditMesh *)handle; + BMVert *eve = BMIter_AtIndex(em->bm, BM_VERTS_OF_MESH, NULL, index-1); + + if(eve && BM_TestHFlag(eve, BM_SELECT)) return 0; + return 1; +} +/** + * findnearestvert + * + * dist (in/out): minimal distance to the nearest and at the end, actual distance + * sel: selection bias + * if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts + * if 0, unselected vertice are given the bias + * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased + */ +BMVert *EDBM_findnearestvert(ViewContext *vc, int *dist, short sel, short strict) +{ + if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)){ + int distance; + unsigned int index; + BMVert *eve; + + if(strict) index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, strict, vc->em, findnearestvert__backbufIndextest); + else index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, 0, NULL, NULL); + + eve = BMIter_AtIndex(vc->em->bm, BM_VERTS_OF_MESH, NULL, index-1); + + if(eve && distance < *dist) { + *dist = distance; + return eve; + } else { + return NULL; + } + + } + else { + struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; BMVert *closest; } data; + static int lastSelectedIndex=0; + static BMVert *lastSelected=NULL; + + if (lastSelected && BMIter_AtIndex(vc->em->bm, BM_VERTS_OF_MESH, NULL, lastSelectedIndex)!=lastSelected) { + lastSelectedIndex = 0; + lastSelected = NULL; + } + + data.lastIndex = lastSelectedIndex; + data.mval[0] = vc->mval[0]; + data.mval[1] = vc->mval[1]; + data.select = sel; + data.dist = *dist; + data.strict = strict; + data.closest = NULL; + data.closestIndex = 0; + + data.pass = 0; + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + + mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1); + + if (data.dist>3) { + data.pass = 1; + mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1); + } + + *dist = data.dist; + lastSelected = data.closest; + lastSelectedIndex = data.closestIndex; + + return data.closest; + } +} + +/* returns labda for closest distance v1 to line-piece v2-v3 */ +static float labda_PdistVL2Dfl( float *v1, float *v2, float *v3) +{ + float rc[2], len; + + rc[0]= v3[0]-v2[0]; + rc[1]= v3[1]-v2[1]; + len= rc[0]*rc[0]+ rc[1]*rc[1]; + if(len==0.0f) + return 0.0f; + + return ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len; +} + +/* note; uses v3d, so needs active 3d window */ +static void findnearestedge__doClosest(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index) +{ + struct { ViewContext vc; float mval[2]; int dist; BMEdge *closest; } *data = userData; + float v1[2], v2[2]; + int distance; + + v1[0] = x0; + v1[1] = y0; + v2[0] = x1; + v2[1] = y1; + + distance= PdistVL2Dfl(data->mval, v1, v2); + + if(BM_TestHFlag(eed, BM_SELECT)) distance+=5; + if(distance < data->dist) { + if(data->vc.rv3d->rflag & RV3D_CLIPPING) { + float labda= labda_PdistVL2Dfl(data->mval, v1, v2); + float vec[3]; + + vec[0]= eed->v1->co[0] + labda*(eed->v2->co[0] - eed->v1->co[0]); + vec[1]= eed->v1->co[1] + labda*(eed->v2->co[1] - eed->v1->co[1]); + vec[2]= eed->v1->co[2] + labda*(eed->v2->co[2] - eed->v1->co[2]); + Mat4MulVecfl(data->vc.obedit->obmat, vec); + + if(view3d_test_clipping(data->vc.rv3d, vec)==0) { + data->dist = distance; + data->closest = eed; + } + } + else { + data->dist = distance; + data->closest = eed; + } + } +} +BMEdge *EDBM_findnearestedge(ViewContext *vc, int *dist) +{ + + if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) { + int distance; + unsigned int index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_solidoffs, bm_wireoffs, &distance,0, NULL, NULL); + BMEdge *eed = BMIter_AtIndex(vc->em->bm, BM_EDGES_OF_MESH, NULL, index-1); + + if (eed && distance<*dist) { + *dist = distance; + return eed; + } else { + return NULL; + } + } + else { + struct { ViewContext vc; float mval[2]; int dist; BMEdge *closest; } data; + + data.vc= *vc; + data.mval[0] = vc->mval[0]; + data.mval[1] = vc->mval[1]; + data.dist = *dist; + data.closest = NULL; + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + + mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, 2); + + *dist = data.dist; + return data.closest; + } +} + +static void findnearestface__getDistance(void *userData, BMFace *efa, int x, int y, int index) +{ + struct { short mval[2]; int dist; BMFace *toFace; } *data = userData; + + if (efa==data->toFace) { + int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y); + + if (temp<data->dist) + data->dist = temp; + } +} +static void findnearestface__doClosest(void *userData, BMFace *efa, int x, int y, int index) +{ + struct { short mval[2], pass; int dist, lastIndex, closestIndex; BMFace *closest; } *data = userData; + + if (data->pass==0) { + if (index<=data->lastIndex) + return; + } else { + if (index>data->lastIndex) + return; + } + + if (data->dist>3) { + int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y); + + if (temp<data->dist) { + data->dist = temp; + data->closest = efa; + data->closestIndex = index; + } + } +} + +BMFace *EDBM_findnearestface(ViewContext *vc, int *dist) +{ + + if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) { + unsigned int index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]); + BMFace *efa = BMIter_AtIndex(vc->em->bm, BM_FACES_OF_MESH, NULL, index-1); + + if (efa) { + struct { short mval[2]; int dist; BMFace *toFace; } data; + + data.mval[0] = vc->mval[0]; + data.mval[1] = vc->mval[1]; + data.dist = 0x7FFF; /* largest short */ + data.toFace = efa; + + mesh_foreachScreenFace(vc, findnearestface__getDistance, &data); + + if(vc->em->selectmode == SCE_SELECT_FACE || data.dist<*dist) { /* only faces, no dist check */ + *dist= data.dist; + return efa; + } + } + + return NULL; + } + else { + struct { short mval[2], pass; int dist, lastIndex, closestIndex; BMFace *closest; } data; + static int lastSelectedIndex=0; + static BMFace *lastSelected=NULL; + + if (lastSelected && BMIter_AtIndex(vc->em->bm, BM_FACES_OF_MESH, NULL, lastSelectedIndex)!=lastSelected) { + lastSelectedIndex = 0; + lastSelected = NULL; + } + + data.lastIndex = lastSelectedIndex; + data.mval[0] = vc->mval[0]; + data.mval[1] = vc->mval[1]; + data.dist = *dist; + data.closest = NULL; + data.closestIndex = 0; + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + + data.pass = 0; + mesh_foreachScreenFace(vc, findnearestface__doClosest, &data); + + if (data.dist>3) { + data.pass = 1; + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + mesh_foreachScreenFace(vc, findnearestface__doClosest, &data); + } + + *dist = data.dist; + lastSelected = data.closest; + lastSelectedIndex = data.closestIndex; + + return data.closest; + } +} + +/* best distance based on screen coords. + use em->selectmode to define how to use + selected vertices and edges get disadvantage + return 1 if found one +*/ +static int unified_findnearest(ViewContext *vc, BMVert **eve, BMEdge **eed, BMFace **efa) +{ + BMEditMesh *em= vc->em; + int dist= 75; + + *eve= NULL; + *eed= NULL; + *efa= NULL; + + /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ + view3d_validate_backbuf(vc); + + if(em->selectmode & SCE_SELECT_VERTEX) + *eve= EDBM_findnearestvert(vc, &dist, BM_SELECT, 0); + if(em->selectmode & SCE_SELECT_FACE) + *efa= EDBM_findnearestface(vc, &dist); + + dist-= 20; /* since edges select lines, we give dots advantage of 20 pix */ + if(em->selectmode & SCE_SELECT_EDGE) + *eed= EDBM_findnearestedge(vc, &dist); + + /* return only one of 3 pointers, for frontbuffer redraws */ + if(*eed) { + *efa= NULL; *eve= NULL; + } + else if(*efa) { + *eve= NULL; + } + + return (*eve || *eed || *efa); +} + +/* **************** SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */ + +static EnumPropertyItem prop_similar_types[] = { + {SIMVERT_NORMAL, "NORMAL", 0, "Normal", ""}, + {SIMVERT_FACE, "FACE", 0, "Amount of Adjacent Faces", ""}, + {SIMVERT_VGROUP, "VGROUP", 0, "Vertex Groups", ""}, + + {SIMEDGE_LENGTH, "LENGTH", 0, "Length", ""}, + {SIMEDGE_DIR, "DIR", 0, "Direction", ""}, + {SIMEDGE_FACE, "FACE", 0, "Amount of Faces Around an Edge", ""}, + {SIMEDGE_FACE_ANGLE, "FACE_ANGLE", 0, "Face Angles", ""}, + {SIMEDGE_CREASE, "CREASE", 0, "Crease", ""}, + {SIMEDGE_SEAM, "SEAM", 0, "Seam", ""}, + {SIMEDGE_SHARP, "SHARP", 0, "Sharpness", ""}, + + {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""}, + {SIMFACE_IMAGE, "IMAGE", 0, "Image", ""}, + {SIMFACE_AREA, "AREA", 0, "Area", ""}, + {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""}, + {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""}, + {SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""}, + + {0, NULL, 0, NULL, NULL} +}; + +/* selects new faces/edges/verts based on the existing selection */ + +static int similar_face_select_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_edit_object(C); + BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh; + BMOperator bmop; + + /* get the type from RNA */ + int type = RNA_enum_get(op->ptr, "type"); + + float thresh = CTX_data_tool_settings(C)->select_thresh; + + /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ + EDBM_InitOpf(em, &bmop, op, "similarfaces faces=%hf type=%d thresh=%f", BM_SELECT, type, thresh); + + /* execute the operator */ + BMO_Exec_Op(em->bm, &bmop); + + /* clear the existing selection */ + EDBM_clear_flag_all(em, BM_SELECT); + + /* select the output */ + BMO_HeaderFlag_Buffer(em->bm, &bmop, "faceout", BM_SELECT, BM_ALL); + + /* finish the operator */ + if( !EDBM_FinishOp(em, &bmop, op, 1) ) + return OPERATOR_CANCELLED; + + /* dependencies graph and notification stuff */ + DAG_id_flush_update(ob->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data); + + /* we succeeded */ + return OPERATOR_FINISHED; +} + +/* ***************************************************** */ + +/* EDGE GROUP */ + +/* wrap the above function but do selection flushing edge to face */ +static int similar_edge_select_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_edit_object(C); + BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh; + BMOperator bmop; + + /* get the type from RNA */ + int type = RNA_enum_get(op->ptr, "type"); + + float thresh = CTX_data_tool_settings(C)->select_thresh; + + /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ + EDBM_InitOpf(em, &bmop, op, "similaredges edges=%he type=%d thresh=%f", BM_SELECT, type, thresh); + + /* execute the operator */ + BMO_Exec_Op(em->bm, &bmop); + + /* clear the existing selection */ + EDBM_clear_flag_all(em, BM_SELECT); + + /* select the output */ + BMO_HeaderFlag_Buffer(em->bm, &bmop, "edgeout", BM_SELECT, BM_ALL); + EDBM_selectmode_flush(em); + + /* finish the operator */ + if( !EDBM_FinishOp(em, &bmop, op, 1) ) + return OPERATOR_CANCELLED; + + /* dependencies graph and notification stuff */ + DAG_id_flush_update(ob->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data); + + /* we succeeded */ + return OPERATOR_FINISHED; +} + +/* ********************************* */ + +/* +VERT GROUP + mode 1: same normal + mode 2: same number of face users + mode 3: same vertex groups +*/ + + +static int similar_vert_select_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_edit_object(C); + BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh; + BMOperator bmop; + /* get the type from RNA */ + int type = RNA_enum_get(op->ptr, "type"); + float thresh = CTX_data_tool_settings(C)->select_thresh; + + /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ + EDBM_InitOpf(em, &bmop, op, "similarverts verts=%hv type=%d thresh=%f", BM_SELECT, type, thresh); + + /* execute the operator */ + BMO_Exec_Op(em->bm, &bmop); + + /* clear the existing selection */ + EDBM_clear_flag_all(em, BM_SELECT); + + /* select the output */ + BMO_HeaderFlag_Buffer(em->bm, &bmop, "vertout", BM_SELECT, BM_ALL); + + /* finish the operator */ + if( !EDBM_FinishOp(em, &bmop, op, 1) ) + return OPERATOR_CANCELLED; + + EDBM_selectmode_flush(em); + + /* dependencies graph and notification stuff */ + DAG_id_flush_update(ob->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data); + + /* we succeeded */ + return OPERATOR_FINISHED; +} + +static int select_similar_exec(bContext *C, wmOperator *op) +{ + int type= RNA_enum_get(op->ptr, "type"); + + if(type < 100) + return similar_vert_select_exec(C, op); + else if(type < 200) + return similar_edge_select_exec(C, op); + else + return similar_face_select_exec(C, op); +} + +static EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA *ptr, int *free) +{ + Object *obedit = CTX_data_edit_object(C); + EnumPropertyItem *item= NULL; + int a, totitem= 0; + + if(obedit && obedit->type == OB_MESH) { + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + + if(em->selectmode & SCE_SELECT_VERTEX) { + for (a=SIMVERT_NORMAL; a<SIMEDGE_LENGTH; a++) { + RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a); + } + } else if(em->selectmode & SCE_SELECT_EDGE) { + for (a=SIMEDGE_LENGTH; a<SIMFACE_MATERIAL; a++) { + RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a); + } + } else if(em->selectmode & SCE_SELECT_FACE) { + for (a=SIMFACE_MATERIAL; a<=SIMFACE_COPLANAR; a++) { + RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a); + } + } + RNA_enum_item_end(&item, &totitem); + + *free= 1; + + return item; + } + + return NULL; +} + +void MESH_OT_select_similar(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name= "Select Similar"; + ot->idname= "MESH_OT_select_similar"; + + /* api callbacks */ + ot->invoke= WM_menu_invoke; + ot->exec= select_similar_exec; + ot->poll= ED_operator_editmesh; + ot->description= "Select similar vertices, edges or faces by property types."; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + prop= RNA_def_enum(ot->srna, "type", prop_similar_types, SIMVERT_NORMAL, "Type", ""); + RNA_def_enum_funcs(prop, select_similar_type_itemf); +} + +/* ***************************************************** */ + +/* **************** LOOP SELECTS *************** */ +/*faceloop_select, edgeloop_select, and edgering_select, are left + here for reference purposes temporarily, but have all been replaced + by uses of walker_select.*/ + +static void walker_select(BMEditMesh *em, int walkercode, void *start, int select) +{ + BMesh *bm = em->bm; + BMHeader *h; + BMWalker walker; + + BMW_Init(&walker, bm, walkercode, 0, 0); + h = BMW_Begin(&walker, start); + for (; h; h=BMW_Step(&walker)) { + BM_Select(bm, h, select); + } + BMW_End(&walker); +} + +#if 0 +/* selects quads in loop direction of indicated edge */ +/* only flush over edges with valence <= 2 */ +void faceloop_select(EditMesh *em, EditEdge *startedge, int select) +{ + EditEdge *eed; + EditFace *efa; + int looking= 1; + + /* in eed->f1 we put the valence (amount of faces in edge) */ + /* in eed->f2 we put tagged flag as correct loop */ + /* in efa->f1 we put tagged flag as correct to select */ + + for(eed= em->edges.first; eed; eed= eed->next) { + eed->f1= 0; + eed->f2= 0; + } + for(efa= em->faces.first; efa; efa= efa->next) { + efa->f1= 0; + if(efa->h==0) { + efa->e1->f1++; + efa->e2->f1++; + efa->e3->f1++; + if(efa->e4) efa->e4->f1++; + } + } + + /* tag startedge OK*/ + startedge->f2= 1; + + while(looking) { + looking= 0; + + for(efa= em->faces.first; efa; efa= efa->next) { + if(efa->h==0 && efa->e4 && efa->f1==0) { /* not done quad */ + if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */ + + /* if edge tagged, select opposing edge and mark face ok */ + if(efa->e1->f2) { + efa->e3->f2= 1; + efa->f1= 1; + looking= 1; + } + else if(efa->e2->f2) { + efa->e4->f2= 1; + efa->f1= 1; + looking= 1; + } + if(efa->e3->f2) { + efa->e1->f2= 1; + efa->f1= 1; + looking= 1; + } + if(efa->e4->f2) { + efa->e2->f2= 1; + efa->f1= 1; + looking= 1; + } + } + } + } + } + + /* (de)select the faces */ + if(select!=2) { + for(efa= em->faces.first; efa; efa= efa->next) { + if(efa->f1) EM_select_face(efa, select); + } + } +} +#endif + + +/* selects or deselects edges that: +- if edges has 2 faces: + - has vertices with valence of 4 + - not shares face with previous edge +- if edge has 1 face: + - has vertices with valence 4 + - not shares face with previous edge + - but also only 1 face +- if edge no face: + - has vertices with valence 2 +*/ + +/* + Almostly exactly the same code as faceloop select +*/ +static void edgering_select(BMEditMesh *em, BMEdge *startedge, int select) +{ +#if 0 //BMESH_TODO + BMEdge *eed; + BMFace *efa; + int looking= 1; + + /* in eed->f1 we put the valence (amount of faces in edge) */ + /* in eed->f2 we put tagged flag as correct loop */ + /* in efa->f1 we put tagged flag as correct to select */ + + for(eed= em->edges.first; eed; eed= eed->next) { + eed->f1= 0; + eed->f2= 0; + } + for(efa= em->faces.first; efa; efa= efa->next) { + efa->f1= 0; + if(efa->h==0) { + efa->e1->f1++; + efa->e2->f1++; + efa->e3->f1++; + if(efa->e4) efa->e4->f1++; + } + } + + /* tag startedge OK */ + startedge->f2= 1; + + while(looking) { + looking= 0; + + for(efa= em->faces.first; efa; efa= efa->next) { + if(efa->e4 && efa->f1==0 && !efa->h) { /* not done quad */ + if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */ + + /* if edge tagged, select opposing edge and mark face ok */ + if(efa->e1->f2) { + efa->e3->f2= 1; + efa->f1= 1; + looking= 1; + } + else if(efa->e2->f2) { + efa->e4->f2= 1; + efa->f1= 1; + looking= 1; + } + if(efa->e3->f2) { + efa->e1->f2= 1; + efa->f1= 1; + looking= 1; + } + if(efa->e4->f2) { + efa->e2->f2= 1; + efa->f1= 1; + looking= 1; + } + } + } + } + } + + /* (de)select the edges */ + for(eed= em->edges.first; eed; eed= eed->next) { + if(eed->f2) EM_select_edge(eed, select); + } +#endif +} + +static int loop_multiselect(bContext *C, wmOperator *op) +{ +#if 0 //BMESH_TODO + Object *obedit= CTX_data_edit_object(C); + BMEditMesh *em= EM_GetBMEditMesh(((Mesh *)obedit->data)); + BMEdge *eed; + BMEdge **edarray; + int edindex, edfirstcount; + int looptype= RNA_boolean_get(op->ptr, "ring"); + + /* sets em->totedgesel */ + EM_nedges_selected(em); + + edarray = MEM_mallocN(sizeof(BMEdge*)*em->totedgesel,"edge array"); + edindex = 0; + edfirstcount = em->totedgesel; + + for(eed=em->edges.first; eed; eed=eed->next){ + if(eed->f&SELECT){ + edarray[edindex] = eed; + edindex += 1; + } + } + + if(looptype){ + for(edindex = 0; edindex < edfirstcount; edindex +=1){ + eed = edarray[edindex]; + edgering_select(em, eed,SELECT); + } + EM_selectmode_flush(em); + } + else{ + for(edindex = 0; edindex < edfirstcount; edindex +=1){ + eed = edarray[edindex]; + edgeloop_select(em, eed,SELECT); + } + EM_selectmode_flush(em); + } + MEM_freeN(edarray); +// if (EM_texFaceCheck()) + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit); + + EM_EndBMEditMesh(obedit->data, em); +#endif + return OPERATOR_FINISHED; +} + +void MESH_OT_loop_multi_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Multi Select Loops"; + ot->idname= "MESH_OT_loop_multi_select"; + + /* api callbacks */ + ot->exec= loop_multiselect; + ot->poll= ED_operator_editmesh; + ot->description= "Select a loop of connected edges by connection type."; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "ring", 0, "Ring", ""); +} + + +/* ***************** MAIN MOUSE SELECTION ************** */ + + +/* ***************** loop select (non modal) ************** */ + +static void mouse_mesh_loop(bContext *C, short mval[2], short extend, short ring) +{ + ViewContext vc; + BMEditMesh *em; + BMEdge *eed; + int select= 1; + int dist= 50; + + em_setup_viewcontext(C, &vc); + vc.mval[0]= mval[0]; + vc.mval[1]= mval[1]; + em= vc.em; + + /* no afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad */ + view3d_validate_backbuf(&vc); + + eed= EDBM_findnearestedge(&vc, &dist); + if(eed) { + if(extend==0) EDBM_clear_flag_all(em, BM_SELECT); + + if(BM_TestHFlag(em, BM_SELECT)==0) select=1; + else if(extend) select=0; + + if(em->selectmode & SCE_SELECT_FACE) { + walker_select(em, BMW_FACELOOP, eed, select); + } + else if(em->selectmode & SCE_SELECT_EDGE) { + if(ring) + walker_select(em, BMW_EDGERING, eed, select); + else + walker_select(em, BMW_LOOP, eed, select); + } + else if(em->selectmode & SCE_SELECT_VERTEX) { + if(ring) + walker_select(em, BMW_EDGERING, eed, select); + else + walker_select(em, BMW_LOOP, eed, select); + } + + EDBM_selectmode_flush(em); +// if (EM_texFaceCheck()) + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit); + } +} + +static int mesh_select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + + view3d_operator_needs_opengl(C); + + mouse_mesh_loop(C, event->mval, RNA_boolean_get(op->ptr, "extend"), + RNA_boolean_get(op->ptr, "ring")); + + /* cannot do tweaks for as long this keymap is after transform map */ + return OPERATOR_FINISHED; +} + +void MESH_OT_loop_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Loop Select"; + ot->idname= "MESH_OT_loop_select"; + + /* api callbacks */ + ot->invoke= mesh_select_loop_invoke; + ot->poll= ED_operator_editmesh; + ot->description= "Select a loop of connected edges."; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); + RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", ""); +} + +/* ******************* mesh shortest path select, uses prev-selected edge ****************** */ + +/* since you want to create paths with multiple selects, it doesn't have extend option */ +static void mouse_mesh_shortest_path(bContext *C, short mval[2]) +{ +#if 0 //BMESH_TODO + ViewContext vc; + BMEditMesh *em; + BMEdge *eed; + int dist= 50; + + em_setup_viewcontext(C, &vc); + vc.mval[0]= mval[0]; + vc.mval[1]= mval[1]; + em= vc.em; + + eed= findnearestedge(&vc, &dist); + if(eed) { + Mesh *me= vc.obedit->data; + int path = 0; + + if (em->bm->selected.last) { + EditSelection *ese = em->bm->selected.last; + + if(ese && ese->type == BMEdge) { + BMEdge *eed_act; + eed_act = (BMEdge*)ese->data; + if (eed_act != eed) { + if (edgetag_shortest_path(vc.scene, em, eed_act, eed)) { + EM_remove_selection(em, eed_act, BMEdge); + path = 1; + } + } + } + } + if (path==0) { + int act = (edgetag_context_check(vc.scene, eed)==0); + edgetag_context_set(vc.scene, eed, act); /* switch the edge option */ + } + + EM_selectmode_flush(em); + + /* even if this is selected it may not be in the selection list */ + if(edgetag_context_check(vc.scene, eed)==0) + EDBM_remove_selection(em, eed); + else + EDBM_store_selection(em, eed); + + /* force drawmode for mesh */ + switch (CTX_data_tool_settings(C)->edge_mode) { + + case EDGE_MODE_TAG_SEAM: + me->drawflag |= ME_DRAWSEAMS; + break; + case EDGE_MODE_TAG_SHARP: + me->drawflag |= ME_DRAWSHARP; + break; + case EDGE_MODE_TAG_CREASE: + me->drawflag |= ME_DRAWCREASES; + break; + case EDGE_MODE_TAG_BEVEL: + me->drawflag |= ME_DRAWBWEIGHTS; + break; + } + + DAG_id_flush_update(ob->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data); + } +#endif +} + + +static int mesh_shortest_path_select_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + + view3d_operator_needs_opengl(C); + + mouse_mesh_shortest_path(C, event->mval); + + return OPERATOR_FINISHED; +} + +void MESH_OT_select_shortest_path(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Shortest Path Select"; + ot->idname= "MESH_OT_select_shortest_path"; + + /* api callbacks */ + ot->invoke= mesh_shortest_path_select_invoke; + ot->poll= ED_operator_editmesh; + ot->description= "Select shortest path between two selections."; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); +} + + +/* ************************************************** */ +/* here actual select happens */ +/* gets called via generic mouse select operator */ +void mouse_mesh(bContext *C, short mval[2], short extend) +{ + ViewContext vc; + BMVert *eve = NULL; + BMEdge *eed = NULL; + BMFace *efa = NULL; + + /* setup view context for argument to callbacks */ + em_setup_viewcontext(C, &vc); + vc.mval[0]= mval[0]; + vc.mval[1]= mval[1]; + + if(unified_findnearest(&vc, &eve, &eed, &efa)) { + + if(extend==0) EDBM_clear_flag_all(vc.em, BM_SELECT); + + if(efa) { + /* set the last selected face */ + EDBM_set_actFace(vc.em, efa); + + if(!BM_TestHFlag(efa, BM_SELECT)) { + EDBM_store_selection(vc.em, efa); + BM_Select(vc.em->bm, efa, 1); + } + else if(extend) { + EDBM_remove_selection(vc.em, efa); + BM_Select(vc.em->bm, efa, 0); + } + } + else if(eed) { + if(!BM_TestHFlag(eed, BM_SELECT)) { + EDBM_store_selection(vc.em, eed); + BM_Select(vc.em->bm, eed, 1); + } + else if(extend) { + EDBM_remove_selection(vc.em, eed); + BM_Select(vc.em->bm, eed, 0); + } + } + else if(eve) { + if(!BM_TestHFlag(eve, BM_SELECT)) { + EDBM_store_selection(vc.em, eve); + BM_Select(vc.em->bm, eve, 1); + } + else if(extend){ + EDBM_remove_selection(vc.em, eve); + BM_Select(vc.em->bm, eve, 0); + } + } + + EDBM_selectmode_flush(vc.em); + +// if (EM_texFaceCheck()) { + + if (efa && efa->mat_nr != vc.obedit->actcol-1) { + vc.obedit->actcol= efa->mat_nr+1; + vc.em->mat_nr= efa->mat_nr; +// BIF_preview_changed(ID_MA); + } + } + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit); +} + +static void EDBM_strip_selections(BMEditMesh *em) +{ + BMEditSelection *ese, *nextese; + + if(!(em->selectmode & SCE_SELECT_VERTEX)){ + ese = em->bm->selected.first; + while(ese){ + nextese = ese->next; + if(ese->type == BM_VERT) BLI_freelinkN(&(em->bm->selected),ese); + ese = nextese; + } + } + if(!(em->selectmode & SCE_SELECT_EDGE)){ + ese=em->bm->selected.first; + while(ese){ + nextese = ese->next; + if(ese->type == BM_EDGE) BLI_freelinkN(&(em->bm->selected), ese); + ese = nextese; + } + } + if(!(em->selectmode & SCE_SELECT_FACE)){ + ese=em->bm->selected.first; + while(ese){ + nextese = ese->next; + if(ese->type == BM_FACE) BLI_freelinkN(&(em->bm->selected), ese); + ese = nextese; + } + } +} + +/* when switching select mode, makes sure selection is consistant for editing */ +/* also for paranoia checks to make sure edge or face mode works */ +void EDBM_selectmode_set(BMEditMesh *em) +{ + BMVert *eve; + BMEdge *eed; + BMFace *efa; + BMIter iter; + + em->bm->selectmode = em->selectmode; + + EDBM_strip_selections(em); /*strip BMEditSelections from em->selected that are not relevant to new mode*/ + + if(em->selectmode & SCE_SELECT_VERTEX) { + /*BMIter iter; + + eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL); + for ( ; eed; eed=BMIter_Step(&iter)) BM_Select(em->bm, eed, 0); + + efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL); + for ( ; efa; efa=BMIter_Step(&iter)) BM_Select(em->bm, efa, 0);*/ + + EDBM_selectmode_flush(em); + } + else if(em->selectmode & SCE_SELECT_EDGE) { + /* deselect vertices, and select again based on edge select */ + eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL); + for ( ; eve; eve=BMIter_Step(&iter)) BM_Select(em->bm, eve, 0); + + eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL); + for ( ; eed; eed=BMIter_Step(&iter)) { + if (BM_TestHFlag(eed, BM_SELECT)) + BM_Select(em->bm, eed, 1); + } + + /* selects faces based on edge status */ + EDBM_selectmode_flush(em); + } + else if(em->selectmode & SCE_SELECT_FACE) { + /* deselect eges, and select again based on face select */ + eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL); + for ( ; eed; eed=BMIter_Step(&iter)) BM_Select(em->bm, eed, 0); + + efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL); + for ( ; efa; efa=BMIter_Step(&iter)) { + if (BM_TestHFlag(efa, BM_SELECT)) + BM_Select(em->bm, efa, 1); + } + } +} + +void EDBM_convertsel(BMEditMesh *em, short oldmode, short selectmode) +{ + BMVert *eve; + BMEdge *eed; + BMFace *efa; + BMIter iter; + + /*have to find out what the selectionmode was previously*/ + if(oldmode == SCE_SELECT_VERTEX) { + if(selectmode == SCE_SELECT_EDGE) { + /*select all edges associated with every selected vertex*/ + eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL); + for ( ; eed; eed=BMIter_Step(&iter)) { + if(BM_TestHFlag(eed->v1, BM_SELECT)) BM_Select(em->bm, eed, 1); + else if(BM_TestHFlag(eed->v2, BM_SELECT)) BM_Select(em->bm, eed, 1); + } + } + else if(selectmode == SCE_SELECT_FACE) { + BMIter liter; + BMLoop *l; + + /*select all faces associated with every selected vertex*/ + efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL); + for ( ; efa; efa=BMIter_Step(&iter)) { + l = BMIter_New(&liter, em->bm, BM_LOOPS_OF_FACE, efa); + for (; l; l=BMIter_Step(&liter)) { + if (BM_TestHFlag(l->v, BM_SELECT)) { + BM_Select(em->bm, efa, 1); + break; + } + } + } + } + } + + if(oldmode == SCE_SELECT_EDGE){ + if(selectmode == SCE_SELECT_FACE) { + BMIter liter; + BMLoop *l; + + /*select all faces associated with every selected vertex*/ + efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL); + for ( ; efa; efa=BMIter_Step(&iter)) { + l = BMIter_New(&liter, em->bm, BM_LOOPS_OF_FACE, efa); + for (; l; l=BMIter_Step(&liter)) { + if (BM_TestHFlag(l->v, BM_SELECT)) { + BM_Select(em->bm, efa, 1); + break; + } + } + } + } + } +} + + +void EDBM_select_swap(BMEditMesh *em) /* exported for UV */ +{ + BMIter iter; + BMVert *eve; + BMEdge *eed; + BMFace *efa; + + if(em->bm->selectmode & SCE_SELECT_VERTEX) { + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + if (BM_TestHFlag(eve, BM_HIDDEN)) + continue; + BM_Select(em->bm, eve, !BM_TestHFlag(eve, BM_SELECT)); + } + } + else if(em->selectmode & SCE_SELECT_EDGE) { + BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) { + if (BM_TestHFlag(eed, BM_HIDDEN)) + continue; + BM_Select(em->bm, eed, !BM_TestHFlag(eed, BM_SELECT)); + } + } + else { + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (BM_TestHFlag(efa, BM_HIDDEN)) + continue; + BM_Select(em->bm, efa, !BM_TestHFlag(efa, BM_SELECT)); + } + + } +// if (EM_texFaceCheck()) +} + +static int select_inverse_mesh_exec(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; + + EDBM_select_swap(em); + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit); + + return OPERATOR_FINISHED; +} + +void MESH_OT_select_inverse(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Select Inverse"; + ot->idname= "MESH_OT_select_inverse"; + ot->description= "Select inverse of (un)selected vertices, edges or faces."; + + /* api callbacks */ + ot->exec= select_inverse_mesh_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + + +static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + Object *obedit= CTX_data_edit_object(C); + ViewContext vc; + BMWalker walker; + BMEditMesh *em; + BMVert *eve; + BMEdge *e, *eed; + BMFace *efa; + short done=1, toggle=0; + int sel= !RNA_boolean_get(op->ptr, "deselect"); + int limit= RNA_boolean_get(op->ptr, "limit"); + + /* unified_finednearest needs ogl */ + view3d_operator_needs_opengl(C); + + /* setup view context for argument to callbacks */ + em_setup_viewcontext(C, &vc); + em = vc.em; + + if(vc.em->bm->totedge==0) + return OPERATOR_CANCELLED; + + vc.mval[0]= event->mval[0]; + vc.mval[1]= event->mval[1]; + + /* return warning! */ + + /*if(limit) { + int retval= select_linked_limited_invoke(&vc, 0, sel); + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit); + return retval; + }*/ + + if( unified_findnearest(&vc, &eve, &eed, &efa)==0 ) { + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit); + + return OPERATOR_CANCELLED; + } + + if (efa) { + eed = efa->loopbase->e; + } else if (!eed) { + if (!eve || !eve->edge) + return OPERATOR_CANCELLED; + + eed = eve->edge; + } + + 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); + BM_Select(em->bm, e->v2, sel); + } + BMW_End(&walker); + EDBM_select_flush(em, SCE_SELECT_VERTEX); + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit); + return OPERATOR_FINISHED; +} + +void MESH_OT_select_linked_pick(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Select Linked"; + ot->idname= "MESH_OT_select_linked_pick"; + + /* api callbacks */ + ot->invoke= select_linked_pick_invoke; + ot->poll= ED_operator_editmesh; + ot->description= "select/deselect all vertices linked to the edge under the mouse cursor."; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", ""); + RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", ""); +} + + +static int select_linked_exec(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BLI_array_declare(verts); + BMVert **verts = NULL; + BMIter iter; + BMVert *v; + BMEdge *e; + BMWalker walker; + int i, tot; + + tot = 0; + BM_ITER_SELECT(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) + if (BM_TestHFlag(v, BM_SELECT)) { + BLI_array_growone(verts); + verts[tot++] = v; + } + } + + 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)) { + BM_Select(em->bm, e->v1, 1); + BM_Select(em->bm, e->v2, 1); + } + } + BMW_End(&walker); + EDBM_select_flush(em, SCE_SELECT_VERTEX); + + BLI_array_free(verts); + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit); + + return OPERATOR_FINISHED; +} + +void MESH_OT_select_linked(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Select Linked All"; + ot->idname= "MESH_OT_select_linked"; + + /* api callbacks */ + ot->exec= select_linked_exec; + ot->poll= ED_operator_editmesh; + ot->description= "Select all vertices linked to the active mesh."; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", ""); +} + +/* ******************** **************** */ + +static int select_more(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh; + BMOperator bmop; + int usefaces = em->selectmode > SCE_SELECT_EDGE; + + EDBM_InitOpf(em, &bmop, op, "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, BM_ALL); + + EDBM_selectmode_flush(em); + + if (!EDBM_FinishOp(em, &bmop, op, 1)) + return OPERATOR_CANCELLED; + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit); + return OPERATOR_FINISHED; +} + +void MESH_OT_select_more(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Select More"; + ot->idname= "MESH_OT_select_more"; + ot->description= "Select more vertices, edges or faces connected to initial selection."; + + /* api callbacks */ + ot->exec= select_more; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int select_less(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh; + BMOperator bmop; + int usefaces = em->selectmode > SCE_SELECT_EDGE; + + EDBM_InitOpf(em, &bmop, op, "regionextend geom=%hvef constrict=%d usefaces=%d", + BM_SELECT, 1, usefaces); + + BMO_Exec_Op(em->bm, &bmop); + BMO_UnHeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL); + + EDBM_selectmode_flush(em); + + if (!EDBM_FinishOp(em, &bmop, op, 1)) + return OPERATOR_CANCELLED; + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit); + return OPERATOR_FINISHED; +} + +void MESH_OT_select_less(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Select Less"; + ot->idname= "MESH_OT_select_less"; + ot->description= "Deselect vertices, edges or faces at the boundary of each selection region."; + + /* api callbacks */ + ot->exec= select_less; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} diff --git a/source/blender/editors/mesh/bmesh_selecthistory.c b/source/blender/editors/mesh/bmesh_selecthistory.c new file mode 100644 index 00000000000..25c037170fa --- /dev/null +++ b/source/blender/editors/mesh/bmesh_selecthistory.c @@ -0,0 +1,126 @@ +/** + * $Id: + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/* ********* Selection History ************ */ + +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_mesh_types.h" +#include "DNA_material_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_texture_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_view3d_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_rand.h" +#include "BLI_array.h" + +#include "BKE_context.h" +#include "BKE_displist.h" +#include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" +#include "BKE_customdata.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_material.h" +#include "BKE_texture.h" +#include "BKE_utildefines.h" +#include "BKE_report.h" +#include "BKE_tessmesh.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +#include "RE_render_ext.h" /* externtex */ + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "ED_mesh.h" +#include "ED_screen.h" +#include "ED_view3d.h" +#include "bmesh.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "mesh_intern.h" + +#include "BLO_sys_types.h" // for intptr_t support + +/*these wrap equivilent bmesh functions. I'm in two minds of it we should + just use the bm functions directly; on the one hand, there's no real + need (at the moment) to wrap them, but on the other hand having these + wrapped avoids a confusing mess of mixing BM_ and EDBM_ namespaces.*/ + +void EDBM_editselection_center(BMEditMesh *em, float *center, BMEditSelection *ese) +{ + BM_editselection_center(em->bm, center, ese); +} + +void EDBM_editselection_normal(float *normal, BMEditSelection *ese) +{ + BM_editselection_normal(normal, ese); +} + +/* Calculate a plane that is rightangles to the edge/vert/faces normal +also make the plane run allong an axis that is related to the geometry, +because this is used for the manipulators Y axis.*/ +void EDBM_editselection_plane(BMEditMesh *em, float *plane, BMEditSelection *ese) +{ + BM_editselection_plane(em->bm, plane, ese); +} + +void EDBM_remove_selection(BMEditMesh *em, void *data) +{ + BM_remove_selection(em->bm, data); +} + +void EDBM_store_selection(BMEditMesh *em, void *data) +{ + BM_store_selection(em->bm, data); +} + +void EDBM_validate_selections(BMEditMesh *em) +{ + BM_validate_selections(em->bm); +} diff --git a/source/blender/editors/mesh/bmesh_tools.c b/source/blender/editors/mesh/bmesh_tools.c new file mode 100644 index 00000000000..ad1654d2f3a --- /dev/null +++ b/source/blender/editors/mesh/bmesh_tools.c @@ -0,0 +1,3364 @@ + /* $Id: bmesh_tools.c + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2004 by Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joseph Eagar + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <math.h> +#include <float.h> + +#include "MEM_guardedalloc.h" +#include "PIL_time.h" + +#include "BLO_sys_types.h" // for intptr_t support + +#include "DNA_mesh_types.h" +#include "DNA_material_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_view3d_types.h" +#include "DNA_key_types.h" +#include "DNA_windowmanager_types.h" + +#include "RNA_types.h" +#include "RNA_define.h" +#include "RNA_access.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_editVert.h" +#include "BLI_rand.h" +#include "BLI_ghash.h" +#include "BLI_linklist.h" +#include "BLI_heap.h" +#include "BLI_array.h" + +#include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_depsgraph.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" +#include "BKE_bmesh.h" +#include "BKE_report.h" +#include "BKE_tessmesh.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_mesh.h" +#include "ED_view3d.h" +#include "ED_util.h" +#include "ED_screen.h" +#include "ED_transform.h" + +#include "UI_interface.h" + +#include "mesh_intern.h" +#include "bmesh.h" + +#include "editbmesh_bvh.h" + +static void add_normal_aligned(float *nor, float *add) +{ + if( INPR(nor, add) < -0.9999f) + VecSubf(nor, nor, add); + else + VecAddf(nor, nor, add); +} + + +static int subdivide_exec(bContext *C, wmOperator *op) +{ + ToolSettings *ts = CTX_data_tool_settings(C); + Object *obedit= CTX_data_edit_object(C); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; + int cuts= RNA_int_get(op->ptr,"number_cuts"); + float smooth= 0.292f*RNA_float_get(op->ptr, "smoothness"); + float fractal= RNA_float_get(op->ptr, "fractal")/100; + int flag= 0; + + if(smooth != 0.0f) + flag |= B_SMOOTH; + if(fractal != 0.0f) + flag |= B_FRACTAL; + + BM_esubdivideflag(obedit, em->bm, BM_SELECT, + smooth, fractal, + ts->editbutflag|flag, + cuts, 0, RNA_enum_get(op->ptr, "quadcorner"), + RNA_boolean_get(op->ptr, "tess_single_edge"), + RNA_boolean_get(op->ptr, "gridfill")); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +/* Note, these values must match delete_mesh() event values */ +static EnumPropertyItem prop_mesh_cornervert_types[] = { + {SUBD_INNERVERT, "INNERVERT", 0, "Inner Vert", ""}, + {SUBD_PATH, "PATH", 0, "Path", ""}, + {SUBD_STRAIGHT_CUT, "STRAIGHT_CUT", 0, "Straight Cut", ""}, + {SUBD_FAN, "FAN", 0, "Fan", ""}, + {0, NULL, 0, NULL, NULL} +}; + +void MESH_OT_subdivide(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Subdivide"; + ot->description= "Subdivide selected edges."; + ot->idname= "MESH_OT_subdivide"; + + /* api callbacks */ + ot->exec= subdivide_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_int(ot->srna, "number_cuts", 1, 1, 20, "Number of Cuts", "", 1, INT_MAX); + RNA_def_float(ot->srna, "fractal", 0.0, 0.0f, FLT_MAX, "Fractal", "Fractal randomness factor.", 0.0f, 1000.0f); + RNA_def_float(ot->srna, "smoothness", 0.0f, 0.0f, 1000.0f, "Smoothness", "Smoothness factor.", 0.0f, FLT_MAX); + + /*props */ + RNA_def_enum(ot->srna, "quadcorner", prop_mesh_cornervert_types, SUBD_STRAIGHT_CUT, "Quad Corner Type", "Method used for subdividing two adjacent edges in a quad"); + RNA_def_boolean(ot->srna, "tess_single_edge", 0, "Tesselate Single Edge", "Adds triangles to single edges belonging to triangles or quads"); + RNA_def_boolean(ot->srna, "gridfill", 1, "Grid Fill", "Fill Fully Selected Triangles and Quads With A Grid"); +} + +/* individual face extrude */ +/* will use vertex normals for extrusion directions, so *nor is unaffected */ +short EDBM_Extrude_face_indiv(BMEditMesh *em, wmOperator *op, short flag, float *nor) +{ + 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; + + if(em==NULL) return 0; + + /* selected edges with 1 or more selected face become faces */ + /* selected faces each makes new faces */ + /* always remove old faces, keeps volumes manifold */ + /* select the new extrusion, deselect old */ + + /* step 1; init, count faces in edges */ + recalc_editnormals(em); + + for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0; // new select flag + + for(eed= em->edges.first; eed; eed= eed->next) { + eed->f2= 0; // amount of unselected faces + } + for(efa= em->faces.first; efa; efa= efa->next) { + if(efa->f & SELECT); + else { + efa->e1->f2++; + efa->e2->f2++; + efa->e3->f2++; + if(efa->e4) efa->e4->f2++; + } + } + + /* step 2: make new faces from faces */ + for(efa= em->faces.last; efa; efa= efa->prev) { + if(efa->f & SELECT) { + v1= addvertlist(em, efa->v1->co, efa->v1); + v2= addvertlist(em, efa->v2->co, efa->v2); + v3= addvertlist(em, efa->v3->co, efa->v3); + + v1->f1= v2->f1= v3->f1= 1; + VECCOPY(v1->no, efa->n); + VECCOPY(v2->no, efa->n); + VECCOPY(v3->no, efa->n); + if(efa->v4) { + v4= addvertlist(em, efa->v4->co, efa->v4); + v4->f1= 1; + VECCOPY(v4->no, efa->n); + } + else v4= NULL; + + /* side faces, clockwise */ + addfacelist(em, efa->v2, v2, v1, efa->v1, efa, NULL); + addfacelist(em, efa->v3, v3, v2, efa->v2, efa, NULL); + if(efa->v4) { + addfacelist(em, efa->v4, v4, v3, efa->v3, efa, NULL); + addfacelist(em, efa->v1, v1, v4, efa->v4, efa, NULL); + } + else { + addfacelist(em, efa->v1, v1, v3, efa->v3, efa, NULL); + } + /* top face */ + addfacelist(em, v1, v2, v3, v4, efa, NULL); + } + } + + /* step 3: remove old faces */ + efa= em->faces.first; + while(efa) { + nextfa= efa->next; + if(efa->f & SELECT) { + BLI_remlink(&em->faces, efa); + free_editface(em, efa); + } + efa= nextfa; + } + + /* step 4: redo selection */ + EM_clear_flag_all(em, SELECT); + + for(eve= em->verts.first; eve; eve= eve->next) { + if(eve->f1) eve->f |= SELECT; + } + + EM_select_flush(em); + + return 'n'; +} +#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) +{ + EditVert *eve; + EditEdge *eed; + EditFace *efa; + + for(eve= em->verts.first; eve; eve= eve->next) eve->tmp.v = NULL; + for(eed= em->edges.first; eed; eed= eed->next) { + eed->tmp.f = NULL; + eed->f2= ((eed->f & flag)!=0); + } + + set_edge_directions_f2(em, 2); + + /* sample for next loop */ + for(efa= em->faces.first; efa; efa= efa->next) { + efa->e1->tmp.f = efa; + efa->e2->tmp.f = efa; + efa->e3->tmp.f = efa; + if(efa->e4) efa->e4->tmp.f = efa; + } + /* make the faces */ + for(eed= em->edges.first; eed; eed= eed->next) { + if(eed->f & flag) { + if(eed->v1->tmp.v == NULL) + eed->v1->tmp.v = addvertlist(em, eed->v1->co, eed->v1); + if(eed->v2->tmp.v == NULL) + eed->v2->tmp.v = addvertlist(em, eed->v2->co, eed->v2); + + if(eed->dir==1) + addfacelist(em, eed->v1, eed->v2, + eed->v2->tmp.v, eed->v1->tmp.v, + eed->tmp.f, NULL); + else + addfacelist(em, eed->v2, eed->v1, + eed->v1->tmp.v, eed->v2->tmp.v, + eed->tmp.f, NULL); + + /* for transform */ + if(eed->tmp.f) { + efa = eed->tmp.f; + if (efa->f & SELECT) add_normal_aligned(nor, efa->n); + } + } + } + Normalize(nor); + + /* set correct selection */ + EM_clear_flag_all(em, SELECT); + for(eve= em->verts.last; eve; eve= eve->prev) { + if(eve->tmp.v) { + eve->tmp.v->f |= flag; + } + } + + for(eed= em->edges.first; eed; eed= eed->next) { + if(eed->v1->f & eed->v2->f & flag) eed->f |= flag; + } + + if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // g is grab + 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; + + EDBM_InitOpf(em, &bmop, op, "extrude_vert_indiv verts=%hv", flag); + + /*deselect original verts*/ + 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); + + if (!EDBM_FinishOp(em, &bmop, op, 1)) return 0; + + return 'g'; // g is grab +} + +short EDBM_Extrude_edge(Object *obedit, BMEditMesh *em, int flag, float *nor) +{ + BMesh *bm = em->bm; + BMIter iter; + BMOIter siter; + BMOperator extop; + BMVert *vert; + BMEdge *edge; + BMFace *f; + ModifierData *md; + BMHeader *el; + + BMO_Init_Op(&extop, "extrudefaceregion"); + BMO_HeaderFlag_To_Slot(bm, &extop, "edgefacein", + flag, BM_VERT|BM_EDGE|BM_FACE); + + BM_ITER(vert, &iter, bm, BM_VERTS_OF_MESH, NULL) { + BM_Select(bm, vert, 0); + } + + BM_ITER(edge, &iter, bm, BM_EDGES_OF_MESH, NULL) { + BM_Select(bm, edge, 0); + } + + BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) { + BM_Select(bm, f, 0); + } + + /* If a mirror modifier with clipping is on, we need to adjust some + * of the cases above to handle edges on the line of symmetry. + */ + md = obedit->modifiers.first; + for (; md; md=md->next) { + if (md->type==eModifierType_Mirror) { + MirrorModifierData *mmd = (MirrorModifierData*) md; + + if(mmd->flag & MOD_MIR_CLIPPING) { + float mtx[4][4]; + if (mmd->mirror_ob) { + float imtx[4][4]; + Mat4Invert(imtx, mmd->mirror_ob->obmat); + Mat4MulMat4(mtx, obedit->obmat, imtx); + } + + for (edge=BMIter_New(&iter,bm,BM_EDGES_OF_MESH,NULL); + edge; edge=BMIter_Step(&iter)) + { + if(edge->head.flag & flag) { + float co1[3], co2[3]; + + VecCopyf(co1, edge->v1->co); + VecCopyf(co2, edge->v2->co); + + if (mmd->mirror_ob) { + VecMat4MulVecfl(co1, mtx, co1); + VecMat4MulVecfl(co2, mtx, co2); + } + + if (mmd->flag & MOD_MIR_AXIS_X) + if ( (fabs(co1[0]) < mmd->tolerance) && + (fabs(co2[0]) < mmd->tolerance) ) + BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL); + + if (mmd->flag & MOD_MIR_AXIS_Y) + if ( (fabs(co1[1]) < mmd->tolerance) && + (fabs(co2[1]) < mmd->tolerance) ) + BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL); + + if (mmd->flag & MOD_MIR_AXIS_Z) + if ( (fabs(co1[2]) < mmd->tolerance) && + (fabs(co2[2]) < mmd->tolerance) ) + BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL); + } + } + } + } + } + + BMO_Exec_Op(bm, &extop); + + nor[0] = nor[1] = nor[2] = 0.0f; + + BMO_ITER(el, &siter, bm, &extop, "geomout", BM_ALL) { + BM_Select(bm, el, 1); + + if (el->type == BM_FACE) { + f = (BMFace*)el; + add_normal_aligned(nor, f->no); + }; + } + + Normalize(nor); + + BMO_Finish_Op(bm, &extop); + + if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // grab + return 'n'; // normal constraint + +} +short EDBM_Extrude_vert(Object *obedit, BMEditMesh *em, short flag, float *nor) +{ + BMIter iter; + BMEdge *eed; + + /*ensure vert flags are consistent for edge selections*/ + eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL); + for ( ; eed; eed=BMIter_Step(&iter)) { + if (BM_TestHFlag(eed, flag)) { + if (flag != BM_SELECT) { + BM_SetHFlag(eed->v1, flag); + BM_SetHFlag(eed->v2, flag); + } else { + BM_Select(em->bm, eed->v1, 1); + BM_Select(em->bm, eed->v2, 1); + } + } else { + if (BM_TestHFlag(eed->v1, flag) && BM_TestHFlag(eed->v2, flag)) { + if (flag != BM_SELECT) + BM_SetHFlag(eed, flag); + else BM_Select(em->bm, eed, 1); + } + } + } + + return EDBM_Extrude_edge(obedit, em, flag, nor); + +} + +static int extrude_repeat_mesh(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + Scene *scene = CTX_data_scene(C); + BMEditMesh *em = ((Mesh *)obedit->data)->edit_btmesh; + RegionView3D *rv3d = CTX_wm_region_view3d(C); + + 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; + + /* dvec */ + dvec[0]= rv3d->persinv[2][0]; + dvec[1]= rv3d->persinv[2][1]; + dvec[2]= rv3d->persinv[2][2]; + Normalize(dvec); + dvec[0]*= offs; + dvec[1]*= offs; + dvec[2]*= offs; + + /* base correction */ + Mat3CpyMat4(bmat, obedit->obmat); + Mat3Inv(tmat, bmat); + Mat3MulVecfl(tmat, dvec); + + for(a=0; a<steps; a++) { + EDBM_Extrude_edge(obedit, em, BM_SELECT, nor); + //BMO_CallOpf(em->bm, "extrudefaceregion edgefacein=%hef", BM_SELECT); + BMO_CallOpf(em->bm, "translate vec=%v verts=%hv", (float*)dvec, BM_SELECT); + //extrudeflag(obedit, em, SELECT, nor); + //translateflag(em, SELECT, dvec); + } + + EDBM_RecalcNormals(em); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_extrude_repeat(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Extrude Repeat Mesh"; + ot->description= "Extrude selected vertices, edges or faces repeatedly."; + ot->idname= "MESH_OT_extrude_repeat"; + + /* api callbacks */ + ot->exec= extrude_repeat_mesh; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, 100.0f, "Offset", "", 0.0f, FLT_MAX); + RNA_def_int(ot->srna, "steps", 10, 0, 180, "Steps", "", 0, INT_MAX); +} + +/* generic extern called extruder */ +int EDBM_Extrude_Mesh(Object *obedit, BMEditMesh *em, wmOperator *op, float *norin) +{ + Scene *scene= NULL; // XXX CTX! + short nr, transmode= 0; + float stacknor[3] = {0.0f, 0.0f, 0.0f}; + 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; + else if(em->bm->totedgesel==0) nr= 4; + else if(em->bm->totfacesel==0) + nr= 3; // pupmenu("Extrude %t|Only Edges%x3|Only Vertices%x4"); + else if(em->bm->totfacesel==1) + nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3|Only Vertices%x4"); + else + nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4"); + } + else if(em->selectmode & SCE_SELECT_EDGE) { + if (em->bm->totedgesel==0) nr = 0; + + nr = 1; + /*else if (em->totedgesel==1) nr = 3; + else if(em->totfacesel==0) nr = 3; + else if(em->totfacesel==1) + nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3"); + else + nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3"); + */ + } + else { + if (em->bm->totfacesel == 0) nr = 0; + else if (em->bm->totfacesel == 1) nr = 1; + 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, 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"); + } + else { + + /* We need to force immediate calculation here because + * transform may use derived objects (which are now stale). + * + * This shouldn't be necessary, derived queries should be + * automatically building this data if invalid. Or something. + */ +// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); + object_handle_update(scene, obedit); + + /* individual faces? */ +// BIF_TransformSetUndo("Extrude"); + if(nr==2) { +// initTransform(TFM_SHRINKFATTEN, CTX_NO_PET|CTX_NO_MIRROR); +// Transform(); + } + else { +// initTransform(TFM_TRANSLATION, CTX_NO_PET|CTX_NO_MIRROR); + if(transmode=='n') { + Mat4MulVecfl(obedit->obmat, nor); + VecSubf(nor, nor, obedit->obmat[3]); +// BIF_setSingleAxisConstraint(nor, "along normal"); + } +// Transform(); + } + } + + return transmode; +} + +/* 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_GEOM|ND_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_edge(obedit, em, BM_SELECT, nor); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + 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_region(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Extrude Region"; + ot->idname= "MESH_OT_extrude_region"; + + /* api callbacks */ + ot->invoke= mesh_extrude_region_invoke; + ot->exec= mesh_extrude_region_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_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_GEOM|ND_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_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + 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_GEOM|ND_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_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + 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_GEOM|ND_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_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + 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->description= "Extrude selected vertices, edges or faces."; + 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 */ +{ + if(em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel) + EDBM_clear_flag_all(em, SELECT); + else + EDBM_set_flag_all(em, SELECT); +} + +static int toggle_select_all_exec(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; + + EDBM_toggle_select_all(em); + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit); + + return OPERATOR_FINISHED; +} + +void MESH_OT_select_all_toggle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Select/Deselect All"; + ot->idname= "MESH_OT_select_all_toggle"; + ot->description= "(de)select all vertices, edges or faces."; + + /* api callbacks */ + ot->exec= toggle_select_all_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/* *************** add-click-mesh (extrude) operator ************** */ + +static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event) +{ + ViewContext vc; + BMVert *v1; + BMIter iter; + float min[3], max[3]; + int done= 0; + + em_setup_viewcontext(C, &vc); + + INIT_MINMAX(min, max); + + BM_ITER_SELECT(v1, &iter, vc.em->bm, BM_VERTS_OF_MESH, NULL) + DO_MINMAX(v1->co, min, max); + done= 1; + } + + /* call extrude? */ + if(done) { + BMEdge *eed; + float vec[3], cent[3], mat[3][3]; + float nor[3]= {0.0, 0.0, 0.0}; + + /* check for edges that are half selected, use for rotation */ + done= 0; + BM_ITER(eed, &iter, vc.em->bm, BM_EDGES_OF_MESH, NULL) { + if (BM_TestHFlag(eed->v1, BM_SELECT) ^ BM_TestHFlag(eed->v2, BM_SELECT)) { + if(BM_TestHFlag(eed->v1, BM_SELECT)) + VecSubf(vec, eed->v1->co, eed->v2->co); + else + VecSubf(vec, eed->v2->co, eed->v1->co); + VecAddf(nor, nor, vec); + done= 1; + } + } + if(done) Normalize(nor); + + /* center */ + VecAddf(cent, min, max); + VecMulf(cent, 0.5f); + VECCOPY(min, cent); + + Mat4MulVecfl(vc.obedit->obmat, min); // view space + view3d_get_view_aligned_coordinate(&vc, min, event->mval); + Mat4Invert(vc.obedit->imat, vc.obedit->obmat); + Mat4MulVecfl(vc.obedit->imat, min); // back in object space + + VecSubf(min, min, cent); + + /* calculate rotation */ + Mat3One(mat); + if(done) { + float dot; + + VECCOPY(vec, min); + Normalize(vec); + dot= INPR(vec, nor); + + if( fabs(dot)<0.999) { + float cross[3], si, q1[4]; + + Crossf(cross, nor, vec); + Normalize(cross); + dot= 0.5f*saacos(dot); + si= (float)sin(dot); + q1[0]= (float)cos(dot); + q1[1]= cross[0]*si; + q1[2]= cross[1]*si; + q1[3]= cross[2]*si; + + QuatToMat3(q1, mat); + } + } + + + EDBM_Extrude_edge(vc.obedit, vc.em, SELECT, nor); + EDBM_CallOpf(vc.em, op, "rotate verts=%hv cent=%v mat=%m3", + BM_SELECT, cent, mat); + EDBM_CallOpf(vc.em, op, "translate verts=%hv vec=%v", + BM_SELECT, min); + } + else { + float *curs= give_cursor(vc.scene, vc.v3d); + BMOperator bmop; + BMOIter oiter; + + VECCOPY(min, curs); + + view3d_get_view_aligned_coordinate(&vc, min, event->mval); + Mat4Invert(vc.obedit->imat, vc.obedit->obmat); + Mat4MulVecfl(vc.obedit->imat, min); // back in object space + + EDBM_InitOpf(vc.em, &bmop, op, "makevert co=%v", min); + BMO_Exec_Op(vc.em->bm, &bmop); + + BMO_ITER(v1, &oiter, vc.em->bm, &bmop, "newvertout", BM_VERT) { + BM_Select(vc.em->bm, v1, 1); + } + + if (!EDBM_FinishOp(vc.em, &bmop, op, 1)) + return OPERATOR_CANCELLED; + } + + //retopo_do_all(); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, vc.obedit->data); + DAG_id_flush_update(vc.obedit->data, OB_RECALC_DATA); + + return OPERATOR_FINISHED; +} + +void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Duplicate or Extrude at 3D Cursor"; + ot->idname= "MESH_OT_dupli_extrude_cursor"; + + /* api callbacks */ + ot->invoke= dupli_extrude_cursor; + ot->description= "Duplicate and extrude selected vertices, edges or faces towards the mouse cursor."; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int delete_mesh(bContext *C, Object *obedit, wmOperator *op, int event, Scene *scene) +{ + BMEditMesh *bem = ((Mesh*)obedit->data)->edit_btmesh; + + if(event<1) return OPERATOR_CANCELLED; + + if(event==10 ) { + //"Erase Vertices"; + + if (!EDBM_CallOpf(bem, op, "del geom=%hv context=%i", BM_SELECT, DEL_VERTS)) + return OPERATOR_CANCELLED; + } + else if(event==11) { + //"Edge Loop" + if (!EDBM_CallOpf(bem, op, "dissolveedgeloop edges=%he", BM_SELECT)) + return OPERATOR_CANCELLED; + } + else if(event==7) { + //"Dissolve" + if (bem->selectmode & SCE_SELECT_FACE) { + if (!EDBM_CallOpf(bem, op, "dissolvefaces faces=%hf",BM_SELECT)) + return OPERATOR_CANCELLED; + } else if (bem->selectmode & SCE_SELECT_EDGE) { + if (!EDBM_CallOpf(bem, op, "dissolveedges edges=%he",BM_SELECT)) + return OPERATOR_CANCELLED; + } else if (bem->selectmode & SCE_SELECT_VERTEX) { + if (!EDBM_CallOpf(bem, op, "dissolveverts verts=%hv",BM_SELECT)) + return OPERATOR_CANCELLED; + } + } + else if(event==4) { + //Edges and Faces + if (!EDBM_CallOpf(bem, op, "del geom=%hef context=%i", BM_SELECT, DEL_EDGESFACES)) + return OPERATOR_CANCELLED; + } + else if(event==1) { + //"Erase Edges" + if (!EDBM_CallOpf(bem, op, "del geom=%he context=%i", BM_SELECT, DEL_EDGES)) + return OPERATOR_CANCELLED; + } + else if(event==2) { + //"Erase Faces"; + if (!EDBM_CallOpf(bem, op, "del geom=%hf context=%i", BM_SELECT, DEL_FACES)) + return OPERATOR_CANCELLED; + } + else if(event==5) { + //"Erase Only Faces"; + if (!EDBM_CallOpf(bem, op, "del geom=%hf context=%d", + BM_SELECT, DEL_ONLYFACES)) + return OPERATOR_CANCELLED; + } + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +/* Note, these values must match delete_mesh() event values */ +static EnumPropertyItem prop_mesh_delete_types[] = { + {7, "DISSOLVE", 0, "Dissolve", ""}, + {10,"VERT", 0, "Vertices", ""}, + {1, "EDGE", 0, "Edges", ""}, + {2, "FACE", 0, "Faces", ""}, + {11, "EDGE_LOOP", 0, "Edge Loop", ""}, + {4, "EDGE_FACE", 0, "Edges & Faces", ""}, + {5, "ONLY_FACE", 0, "Only Faces", ""}, + {0, NULL, 0, NULL, NULL} +}; + +static int delete_mesh_exec(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + Scene *scene = CTX_data_scene(C); + + delete_mesh(C, obedit, op, RNA_enum_get(op->ptr, "type"), scene); + + WM_event_add_notifier(C, NC_GEOM|ND_DATA|ND_SELECT, obedit); + + return OPERATOR_FINISHED; +} + +void MESH_OT_delete(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Delete"; + ot->description= "Delete selected vertices, edges or faces."; + ot->idname= "MESH_OT_delete"; + + /* api callbacks */ + ot->invoke= WM_menu_invoke; + ot->exec= delete_mesh_exec; + + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /*props */ + RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, 10, "Type", "Method used for deleting mesh data"); +} + + +static int addedgeface_mesh_exec(bContext *C, wmOperator *op) +{ + BMOperator bmop; + Object *obedit= CTX_data_edit_object(C); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; + + if (!EDBM_InitOpf(em, &bmop, op, "contextual_create geom=%hfev", BM_SELECT)) + return OPERATOR_CANCELLED; + + BMO_Exec_Op(em->bm, &bmop); + BMO_HeaderFlag_Buffer(em->bm, &bmop, "faceout", BM_SELECT, BM_FACE); + + if (!EDBM_FinishOp(em, &bmop, op, 1)) + return OPERATOR_CANCELLED; + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit); + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + + return OPERATOR_FINISHED; +} + +void MESH_OT_edge_face_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Make Edge/Face"; + ot->description= "Add an edge or face to selected."; + ot->idname= "MESH_OT_edge_face_add"; + + /* api callbacks */ + ot->exec= addedgeface_mesh_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + +} + +static EnumPropertyItem prop_mesh_edit_types[] = { + {1, "VERT", 0, "Vertices", ""}, + {2, "EDGE", 0, "Edges", ""}, + {3, "FACE", 0, "Faces", ""}, + {0, NULL, 0, NULL, NULL} +}; + +static int mesh_selection_type_exec(bContext *C, wmOperator *op) +{ + + Object *obedit= CTX_data_edit_object(C); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; + int type = RNA_enum_get(op->ptr,"type"); + + switch (type) { + case 1: + em->selectmode = SCE_SELECT_VERTEX; + break; + case 2: + em->selectmode = SCE_SELECT_EDGE; + break; + case 3: + em->selectmode = SCE_SELECT_FACE; + break; + } + + EDBM_selectmode_set(em); + CTX_data_tool_settings(C)->selectmode = em->selectmode; + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit); + + return OPERATOR_FINISHED; +} + +void MESH_OT_selection_type(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Selection Mode"; + ot->description= "Set the selection mode type."; + ot->idname= "MESH_OT_selection_type"; + + /* api callbacks */ + ot->invoke= WM_menu_invoke; + ot->exec= mesh_selection_type_exec; + + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_enum(ot->srna, "type", prop_mesh_edit_types, 0, "Type", "Set the mesh selection type"); + RNA_def_boolean(ot->srna, "inclusive", 0, "Inclusive", "Selects geometry around selected geometry, occording to selection mode"); +} + +/* ************************* SEAMS AND EDGES **************** */ + +static int editbmesh_mark_seam(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); + Mesh *me= ((Mesh *)obedit->data); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; + BMesh *bm = em->bm; + BMEdge *eed; + BMIter iter; + int clear = RNA_boolean_get(op->ptr, "clear"); + + /* auto-enable seams drawing */ + if(clear==0) { + me->drawflag |= ME_DRAWSEAMS; + } + + if(clear) { + BM_ITER_SELECT(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) + BM_ClearHFlag(eed, BM_SEAM); + } + } + else { + BM_ITER_SELECT(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) + BM_SetHFlag(eed, BM_SEAM); + } + } + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_mark_seam(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Mark Seam"; + ot->idname= "MESH_OT_mark_seam"; + ot->description= "(un)mark selected edges as a seam."; + + /* api callbacks */ + ot->exec= editbmesh_mark_seam; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "clear", 0, "Clear", ""); +} + +static int editbmesh_mark_sharp(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); + Mesh *me= ((Mesh *)obedit->data); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; + BMesh *bm = em->bm; + BMEdge *eed; + BMIter iter; + int clear = RNA_boolean_get(op->ptr, "clear"); + + /* auto-enable sharp edge drawing */ + if(clear == 0) { + me->drawflag |= ME_DRAWSHARP; + } + + if(!clear) { + BM_ITER_SELECT(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) + BM_SetHFlag(eed, BM_SHARP); + } + } else { + BM_ITER_SELECT(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) + BM_ClearHFlag(eed, BM_SHARP); + } + } + + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_mark_sharp(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Mark Sharp"; + ot->idname= "MESH_OT_mark_sharp"; + ot->description= "(un)mark selected edges as sharp."; + + /* api callbacks */ + ot->exec= editbmesh_mark_sharp; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "clear", 0, "Clear", ""); +} + + +static int editbmesh_vert_connect(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); + Mesh *me= ((Mesh *)obedit->data); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; + BMesh *bm = em->bm; + BMOperator bmop; + int len = 0; + + BMO_InitOpf(bm, &bmop, "connectverts verts=%hv", BM_SELECT); + BMO_Exec_Op(bm, &bmop); + len = BMO_GetSlot(&bmop, "edgeout")->len; + BMO_Finish_Op(bm, &bmop); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED; +} + +void MESH_OT_vert_connect(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Vertex Connect"; + ot->idname= "MESH_OT_vert_connect"; + + /* api callbacks */ + ot->exec= editbmesh_vert_connect; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int editbmesh_edge_split(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); + Mesh *me= ((Mesh *)obedit->data); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; + BMesh *bm = em->bm; + BMOperator bmop; + int len = 0; + + BMO_InitOpf(bm, &bmop, "edgesplit edges=%he numcuts=%d", BM_SELECT, RNA_int_get(op->ptr,"number_cuts")); + BMO_Exec_Op(bm, &bmop); + len = BMO_GetSlot(&bmop, "outsplit")->len; + BMO_Finish_Op(bm, &bmop); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED; +} + +void MESH_OT_edge_split(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Edge Split"; + ot->idname= "MESH_OT_edge_split"; + + /* api callbacks */ + ot->exec= editbmesh_edge_split; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_int(ot->srna, "number_cuts", 1, 1, 10, "Number of Cuts", "", 1, INT_MAX); +} + +/****************** add duplicate operator ***************/ + +static int mesh_duplicate_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_edit_object(C); + BMEditMesh *em= ((Mesh*)ob->data)->edit_btmesh; + BMOperator bmop; + + EDBM_InitOpf(em, &bmop, op, "dupe geom=%hvef", BM_SELECT); + + BMO_Exec_Op(em->bm, &bmop); + EDBM_clear_flag_all(em, BM_SELECT); + + BMO_HeaderFlag_Buffer(em->bm, &bmop, "newout", BM_SELECT, BM_ALL); + + if (!EDBM_FinishOp(em, &bmop, op, 1)) + return OPERATOR_CANCELLED; + + DAG_id_flush_update(ob->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); + + return OPERATOR_FINISHED; +} + +static int mesh_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + WM_cursor_wait(1); + mesh_duplicate_exec(C, op); + WM_cursor_wait(0); + + return OPERATOR_FINISHED; +} + +void MESH_OT_duplicate(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Duplicate"; + ot->description= "Duplicate selected vertices, edges or faces."; + ot->idname= "MESH_OT_duplicate"; + + /* api callbacks */ + ot->invoke= mesh_duplicate_invoke; + ot->exec= mesh_duplicate_exec; + + ot->poll= ED_operator_editmesh; + + /* to give to transform */ + RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX); +} + +static int flip_normals(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 (!EDBM_CallOpf(em, op, "reversefaces facaes=%hf", BM_SELECT)) + return OPERATOR_CANCELLED; + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_flip_normals(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Flip Normals"; + ot->description= "Flip the direction of selected face's vertex and face normals"; + ot->idname= "MESH_OT_flip_normals"; + + /* api callbacks */ + ot->exec= flip_normals; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +//#define DIRECTION_CW 1 +//#define DIRECTION_CCW 2 + +static const EnumPropertyItem direction_items[]= { + {DIRECTION_CW, "CW", 0, "Clockwise", ""}, + {DIRECTION_CCW, "CCW", 0, "Counter Clockwise", ""}, + {0, NULL, 0, NULL, NULL}}; + +/* only accepts 1 selected edge, or 2 selected faces */ +static int edge_rotate_selected(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; + BMOperator bmop; + BMEdge *eed; + BMIter iter; + int ccw = RNA_int_get(op->ptr, "direction") == 1; // direction == 2 when clockwise and ==1 for counter CW. + short edgeCount = 0; + + if (!(em->bm->totfacesel == 2 || em->bm->totedgesel == 1)) { + BKE_report(op->reports, RPT_ERROR, "Select one edge or two adjacent faces"); + return OPERATOR_CANCELLED; + } + + /*first see if we have two adjacent faces*/ + BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) { + if (BM_Edge_FaceCount(eed) == 2) { + if ((BM_TestHFlag(eed->loop->f, BM_SELECT) && BM_TestHFlag(((BMLoop*)eed->loop->radial.next->data)->f, BM_SELECT)) + && !(BM_TestHFlag(eed->loop->f, BM_HIDDEN) || BM_TestHFlag(((BMLoop*)eed->loop->radial.next->data)->f, BM_HIDDEN))) + { + break; + } + } + } + + /*ok, we don't have two adjacent faces, but we do have two selected ones. + that's an error condition.*/ + if (!eed && em->bm->totfacesel == 2) { + BKE_report(op->reports, RPT_ERROR, "Select one edge or two adjacent faces"); + return OPERATOR_CANCELLED; + } + + if (!eed) { + BM_ITER_SELECT(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) + if (BM_TestHFlag(eed, BM_SELECT)) + break; + } + } + + /*this should never happen*/ + if (!eed) + return OPERATOR_CANCELLED; + + 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, BM_EDGE); + + if (!EDBM_FinishOp(em, &bmop, op, 1)) + return OPERATOR_CANCELLED; + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_edge_rotate(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Rotate Selected Edge"; + ot->description= "Rotate selected edge or adjoining faces."; + ot->idname= "MESH_OT_edge_rotate"; + + /* api callbacks */ + ot->exec= edge_rotate_selected; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "direction", "direction to rotate edge around."); +} + +/* pinning code */ + +/* swap is 0 or 1, if 1 it pins not selected */ +void EDBM_pin_mesh(BMEditMesh *em, int swap) +{ + BMIter iter; + BMHeader *h; + int itermode; + + if(em==NULL) return; + + if (em->selectmode & SCE_SELECT_VERTEX) + itermode = BM_VERTS_OF_MESH; + else if (em->selectmode & SCE_SELECT_EDGE) + itermode = BM_EDGES_OF_MESH; + else + itermode = BM_FACES_OF_MESH; + + BM_ITER(h, &iter, em->bm, itermode, NULL) { + if (BM_TestHFlag(h, BM_SELECT) ^ swap) + BM_Pin(em->bm, h, 1); + } + + EDBM_selectmode_flush(em); +} + +static int pin_mesh_exec(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + Scene *scene = CTX_data_scene(C); + BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh; + Mesh *me= ((Mesh *)obedit->data); + + me->drawflag |= ME_DRAW_PINS; + + EDBM_pin_mesh(em, RNA_boolean_get(op->ptr, "unselected")); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_pin(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Pin Selection"; + ot->idname= "MESH_OT_pin"; + + /* api callbacks */ + ot->exec= pin_mesh_exec; + ot->poll= ED_operator_editmesh; + ot->description= "Pin (un)selected vertices, edges or faces."; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Pin unselected rather than selected."); +} + +/* swap is 0 or 1, if 1 it unhides not selected */ +void EDBM_unpin_mesh(BMEditMesh *em, int swap) +{ + BMIter iter; + BMHeader *ele; + int i, types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH}; + int sels[3] = {1, !(em->selectmode & SCE_SELECT_VERTEX), !(em->selectmode & SCE_SELECT_VERTEX | SCE_SELECT_EDGE)}; + int itermode; + + if(em==NULL) return; + + if (em->selectmode & SCE_SELECT_VERTEX) + itermode = BM_VERTS_OF_MESH; + else if (em->selectmode & SCE_SELECT_EDGE) + itermode = BM_EDGES_OF_MESH; + else + itermode = BM_FACES_OF_MESH; + + BM_ITER(ele, &iter, em->bm, itermode, NULL) { + if (BM_TestHFlag(ele, BM_SELECT) ^ swap) + BM_Pin(em->bm, ele, 0); + } + + EDBM_selectmode_flush(em); +} + +static int unpin_mesh_exec(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + Scene *scene = CTX_data_scene(C); + BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh; + Mesh *me= ((Mesh *)obedit->data); + + EDBM_unpin_mesh(em, RNA_boolean_get(op->ptr, "unselected")); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_unpin(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Unpin Selection"; + ot->idname= "MESH_OT_unpin"; + ot->description= "Unpin (un)selected vertices, edges or faces."; + + /* api callbacks */ + ot->exec= unpin_mesh_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Unpin unselected rather than selected."); +} + + +/* swap is 0 or 1, if 1 it hides not selected */ +void EDBM_hide_mesh(BMEditMesh *em, int swap) +{ + BMIter iter; + BMHeader *h; + int itermode; + + if(em==NULL) return; + + if (em->selectmode & SCE_SELECT_VERTEX) + itermode = BM_VERTS_OF_MESH; + else if (em->selectmode & SCE_SELECT_EDGE) + itermode = BM_EDGES_OF_MESH; + else + itermode = BM_FACES_OF_MESH; + + BM_ITER(h, &iter, em->bm, itermode, NULL) { + if (BM_TestHFlag(h, BM_SELECT) ^ swap) + BM_Hide(em->bm, h, 1); + } + + /*original hide flushing comment (OUTDATED): + hide happens on least dominant select mode, and flushes up, not down! (helps preventing errors in subsurf) */ + /* - vertex hidden, always means edge is hidden too + - edge hidden, always means face is hidden too + - face hidden, only set face hide + - then only flush back down what's absolute hidden + */ + +} + +static int hide_mesh_exec(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + Scene *scene = CTX_data_scene(C); + BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh; + + EDBM_hide_mesh(em, RNA_boolean_get(op->ptr, "unselected")); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_hide(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Hide Selection"; + ot->idname= "MESH_OT_hide"; + + /* api callbacks */ + ot->exec= hide_mesh_exec; + ot->poll= ED_operator_editmesh; + ot->description= "Hide (un)selected vertices, edges or faces."; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected."); +} + + +void EDBM_reveal_mesh(BMEditMesh *em) +{ + BMIter iter; + BMHeader *ele; + int i, types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH}; + int sels[3] = {1, !(em->selectmode & SCE_SELECT_VERTEX), !(em->selectmode & SCE_SELECT_VERTEX | SCE_SELECT_EDGE)}; + + for (i=0; i<3; i++) { + BM_ITER(ele, &iter, em->bm, types[i], NULL) { + if (BM_TestHFlag(ele, BM_HIDDEN)) { + BM_Hide(em->bm, ele, 0); + + if (sels[i]) + BM_Select(em->bm, ele, 1); + } + } + } + + EDBM_selectmode_flush(em); +} + +static int reveal_mesh_exec(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + Scene *scene = CTX_data_scene(C); + BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh; + + EDBM_reveal_mesh(em); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_reveal(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Reveal Hidden"; + ot->idname= "MESH_OT_reveal"; + ot->description= "Reveal all hidden vertices, edges and faces."; + + /* api callbacks */ + ot->exec= reveal_mesh_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int normals_make_consistent_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 (!EDBM_CallOpf(em, op, "righthandfaces faces=%hf", BM_SELECT)) + return OPERATOR_CANCELLED; + + if (RNA_boolean_get(op->ptr, "inside")) + EDBM_CallOpf(em, op, "reversefaces faces=%hf", BM_SELECT); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_normals_make_consistent(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Make Normals Consistent"; + ot->description= "Make face and vertex normals point either outside or inside the mesh"; + ot->idname= "MESH_OT_normals_make_consistent"; + + /* api callbacks */ + ot->exec= normals_make_consistent_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "inside", 0, "Inside", ""); +} + + + +static int do_smooth_vertex(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; + ModifierData *md; + int mirrx=0, mirry=0, mirrz=0; + int i, repeat; + + /* if there is a mirror modifier with clipping, flag the verts that + * are within tolerance of the plane(s) of reflection + */ + for(md=obedit->modifiers.first; md; md=md->next) { + if(md->type==eModifierType_Mirror) { + MirrorModifierData *mmd = (MirrorModifierData*) md; + + if(mmd->flag & MOD_MIR_CLIPPING) { + if (mmd->flag & MOD_MIR_AXIS_X) + mirrx = 1; + if (mmd->flag & MOD_MIR_AXIS_Y) + mirry = 1; + if (mmd->flag & MOD_MIR_AXIS_Z) + mirrz = 1; + } + } + } + + repeat = RNA_int_get(op->ptr,"repeat"); + if (!repeat) + repeat = 1; + + for (i=0; i<repeat; i++) { + if (!EDBM_CallOpf(em, op, "vertexsmooth verts=%hv mirror_clip_x=%d mirror_clip_y=%d mirror_clip_z=%d", + BM_SELECT, mirrx, mirry, mirrz)) + { + return OPERATOR_CANCELLED; + } + } + + //BMESH_TODO: need to handle the x-axis editing option here properly. + //should probably make a helper function for that? I dunno. + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_vertices_smooth(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Smooth Vertex"; + ot->description= "Flatten angles of selected vertices."; + ot->idname= "MESH_OT_vertices_smooth"; + + /* api callbacks */ + ot->exec= do_smooth_vertex; + 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); +} + + +static int bm_test_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); + RegionView3D *r3d = CTX_wm_region_view3d(C); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; + BMBVHTree *tree = BMBVH_NewBVH(em); + BMIter iter; + BMEdge *e; + + /*hide all back edges*/ + BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) { + if (!BM_TestHFlag(e, BM_SELECT)) + continue; + + if (!BMBVH_EdgeVisible(tree, e, r3d, obedit)) + BM_Select(em->bm, e, 0); + } + + BMBVH_FreeBVH(tree); + +#if 0 //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_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + 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); +} + +/********************** Smooth/Solid Operators *************************/ + +void mesh_set_smooth_faces(BMEditMesh *em, short smooth) +{ + BMIter iter; + BMFace *efa; + + if(em==NULL) return; + + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (BM_TestHFlag(efa, BM_SELECT)) { + if (smooth) + BM_SetHFlag(efa, BM_SMOOTH); + else + BM_ClearHFlag(efa, BM_SMOOTH); + } + } +} + +static int mesh_faces_shade_smooth_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; + + mesh_set_smooth_faces(em, 1); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_faces_shade_smooth(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Shade Smooth"; + ot->description= "Display faces smooth (using vertex normals)."; + ot->idname= "MESH_OT_faces_shade_smooth"; + + /* api callbacks */ + ot->exec= mesh_faces_shade_smooth_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int mesh_faces_shade_flat_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; + + mesh_set_smooth_faces(em, 0); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_faces_shade_flat(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Shade Flat"; + ot->description= "Display faces flat."; + ot->idname= "MESH_OT_faces_shade_flat"; + + /* api callbacks */ + ot->exec= mesh_faces_shade_flat_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + + +/********************** UV/Color Operators *************************/ + + +static const EnumPropertyItem axis_items[]= { + {OPUVC_AXIS_X, "X", 0, "X", ""}, + {OPUVC_AXIS_Y, "Y", 0, "Y", ""}, + {0, NULL, 0, NULL, NULL}}; + +static int mesh_rotate_uvs(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_edit_object(C); + BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh; + BMOperator bmop; + + /* get the direction from RNA */ + int dir = RNA_enum_get(op->ptr, "direction"); + + /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ + EDBM_InitOpf(em, &bmop, op, "meshrotateuvs faces=%hf dir=%d", BM_SELECT, dir); + + /* execute the operator */ + BMO_Exec_Op(em->bm, &bmop); + + /* finish the operator */ + if( !EDBM_FinishOp(em, &bmop, op, 1) ) + return OPERATOR_CANCELLED; + + + /* dependencies graph and notification stuff */ + DAG_id_flush_update(ob->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); +/* DAG_id_flush_update(ob->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); +*/ + /* we succeeded */ + return OPERATOR_FINISHED; +} + +static int mesh_reverse_uvs(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_edit_object(C); + BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh; + BMOperator bmop; + + /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ + EDBM_InitOpf(em, &bmop, op, "meshreverseuvs faces=%hf", BM_SELECT); + + /* execute the operator */ + BMO_Exec_Op(em->bm, &bmop); + + /* finish the operator */ + if( !EDBM_FinishOp(em, &bmop, op, 1) ) + return OPERATOR_CANCELLED; + + /* dependencies graph and notification stuff */ + DAG_id_flush_update(ob->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); +/* DAG_id_flush_update(ob->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); +*/ + /* we succeeded */ + return OPERATOR_FINISHED; +} + +static int mesh_rotate_colors(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_edit_object(C); + BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh; + BMOperator bmop; + + /* get the direction from RNA */ + int dir = RNA_enum_get(op->ptr, "direction"); + + /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ + EDBM_InitOpf(em, &bmop, op, "meshrotatecolors faces=%hf dir=%d", BM_SELECT, dir); + + /* execute the operator */ + BMO_Exec_Op(em->bm, &bmop); + + /* finish the operator */ + if( !EDBM_FinishOp(em, &bmop, op, 1) ) + return OPERATOR_CANCELLED; + + + /* dependencies graph and notification stuff */ + DAG_id_flush_update(ob->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); +/* DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT | ND_GEOM_SELECT, ob); +*/ + /* we succeeded */ + return OPERATOR_FINISHED; +} + + +static int mesh_reverse_colors(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_edit_object(C); + BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh; + BMOperator bmop; + + /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ + EDBM_InitOpf(em, &bmop, op, "meshreversecolors faces=%hf", BM_SELECT); + + /* execute the operator */ + BMO_Exec_Op(em->bm, &bmop); + + /* finish the operator */ + if( !EDBM_FinishOp(em, &bmop, op, 1) ) + return OPERATOR_CANCELLED; + + DAG_id_flush_update(ob->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); + + /* we succeeded */ + return OPERATOR_FINISHED; +#if 0 + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + + EditFace *efa; + short change = 0; + MCol tmpcol, *mcol; + int axis= RNA_enum_get(op->ptr, "axis"); + + if (!EM_vertColorCheck(em)) { + BKE_report(op->reports, RPT_ERROR, "Mesh has no color layers"); + BKE_mesh_end_editmesh(obedit->data, em); + return OPERATOR_CANCELLED; + } + + for(efa=em->faces.first; efa; efa=efa->next) { + if (efa->f & SELECT) { + mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); + if (axis == AXIS_Y) { + tmpcol= mcol[1]; + mcol[1]= mcol[2]; + mcol[2]= tmpcol; + + if(efa->v4) { + tmpcol= mcol[0]; + mcol[0]= mcol[3]; + mcol[3]= tmpcol; + } + } else { + tmpcol= mcol[0]; + mcol[0]= mcol[1]; + mcol[1]= tmpcol; + + if(efa->v4) { + tmpcol= mcol[2]; + mcol[2]= mcol[3]; + mcol[3]= tmpcol; + } + } + change = 1; + } + } + + BKE_mesh_end_editmesh(obedit->data, em); + + if(!change) + return OPERATOR_CANCELLED; + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + +#endif + return OPERATOR_FINISHED; +} + +void MESH_OT_uvs_rotate(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Rotate UVs"; + ot->idname= "MESH_OT_uvs_rotate"; + + /* api callbacks */ + ot->exec= mesh_rotate_uvs; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate UVs around."); +} + +//void MESH_OT_uvs_mirror(wmOperatorType *ot) +void MESH_OT_uvs_reverse(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Reverse UVs"; + ot->idname= "MESH_OT_uvs_reverse"; + + /* api callbacks */ + ot->exec= mesh_reverse_uvs; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + //RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror UVs around."); +} + +void MESH_OT_colors_rotate(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Rotate Colors"; + ot->idname= "MESH_OT_colors_rotate"; + + /* api callbacks */ + ot->exec= mesh_rotate_colors; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate edge around."); +} + +void MESH_OT_colors_reverse(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Reverse Colors"; + ot->idname= "MESH_OT_colors_reverse"; + + /* api callbacks */ + ot->exec= mesh_reverse_colors; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* 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, Object *ob, + int target, int uvmerge, wmOperator *wmop) +{ + BMIter iter; + BMVert *v; + float *vco, co[3], cent[3] = {0.0f, 0.0f, 0.0f}, fac; + int i; + + if (target) { + vco = give_cursor(scene, v3d); + VECCOPY(co, vco); + Mat4MulVecfl(ob->imat, co); + } 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); + VECCOPY(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, obedit, 0, uvs, op); + break; + case 4: + status = merge_target(em, scene, v3d, obedit, 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_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + 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", 1, "UVs", "Move UVs according to merge."); +} + + +static int removedoublesflag_exec(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + Scene *scene = CTX_data_scene(C); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; + BMOperator bmop; + char msg[100]; + int count; + + EDBM_InitOpf(em, &bmop, op, "finddoubles verts=%hv dist=%f", + BM_SELECT, RNA_float_get(op->ptr, "mergedist")); + BMO_Exec_Op(em->bm, &bmop); + + count = BMO_CountSlotMap(em->bm, &bmop, "targetmapout"); + + if (!EDBM_CallOpf(em, op, "weldverts targetmap=%s", &bmop, "targetmapout")) { + BMO_Finish_Op(em->bm, &bmop); + return OPERATOR_CANCELLED; + } + + if (!EDBM_FinishOp(em, &bmop, op, 1)) + return OPERATOR_CANCELLED; + + /*we need a better way of reporting this, since this doesn't work + with the last operator panel correctly. + if(count) + { + sprintf(msg, "Removed %d vertices", count); + BKE_report(op->reports, RPT_INFO, msg); + } + */ + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_remove_doubles(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Remove Doubles"; + ot->idname= "MESH_OT_remove_doubles"; + + /* api callbacks */ + ot->exec= removedoublesflag_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_float(ot->srna, "mergedist", 0.0001f, 0.000001f, 50.0f, + "Merge Distance", + "Minimum distance between elements to merge.", 0.00001, 10.0); +} + +/************************ Vertex Path Operator *************************/ + +typedef struct PathNode { + int u; + int visited; + ListBase edges; +} PathNode; + +typedef struct PathEdge { + struct PathEdge *next, *prev; + int v; + float w; +} PathEdge; + + + +int select_vertex_path_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_edit_object(C); + BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh; + BMOperator bmop; + BMEditSelection *sv, *ev; + + /* get the type from RNA */ + int type = RNA_enum_get(op->ptr, "type"); + + sv = em->bm->selected.last; + if( sv != NULL ) + ev = sv->prev; + else return OPERATOR_CANCELLED; + if( ev == NULL ) + return OPERATOR_CANCELLED; + + if( sv->type != BM_VERT || ev->type != BM_VERT ) + return OPERATOR_CANCELLED; + + /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ + EDBM_InitOpf(em, &bmop, op, "vertexshortestpath startv=%e endv=%e type=%d", sv->data, ev->data, type); + + /* execute the operator */ + BMO_Exec_Op(em->bm, &bmop); + + /* DO NOT clear the existing selection */ + /* EDBM_clear_flag_all(em, BM_SELECT); */ + + /* select the output */ + BMO_HeaderFlag_Buffer(em->bm, &bmop, "vertout", BM_SELECT, BM_ALL); + + /* finish the operator */ + if( !EDBM_FinishOp(em, &bmop, op, 1) ) + return OPERATOR_CANCELLED; + + EDBM_selectmode_flush(em); + + /* dependencies graph and notification stuff */ +/* DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT | ND_GEOM_SELECT, ob); +*/ + DAG_id_flush_update(ob->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); + + + /* we succeeded */ + return OPERATOR_FINISHED; +#if 0 + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + EditVert *eve, *s, *t; + EditEdge *eed; + EditSelection *ese; + PathEdge *newpe, *currpe; + PathNode *currpn; + PathNode *Q; + int v, *previous, pathvert, pnindex; /*pnindex redundant?*/ + int unbalanced, totnodes; + short physical; + float *cost; + Heap *heap; /*binary heap for sorting pointers to PathNodes based upon a 'cost'*/ + + s = t = NULL; + + ese = ((EditSelection*)em->selected.last); + if(ese && ese->type == EDITVERT && ese->prev && ese->prev->type == EDITVERT){ + physical= pupmenu("Distance Method? %t|Edge Length%x1|Topological%x0"); + + t = (EditVert*)ese->data; + s = (EditVert*)ese->prev->data; + + /*need to find out if t is actually reachable by s....*/ + for(eve=em->verts.first; eve; eve=eve->next){ + eve->f1 = 0; + } + + s->f1 = 1; + + unbalanced = 1; + totnodes = 1; + while(unbalanced){ + unbalanced = 0; + for(eed=em->edges.first; eed; eed=eed->next){ + if(!eed->h){ + if(eed->v1->f1 && !eed->v2->f1){ + eed->v2->f1 = 1; + totnodes++; + unbalanced = 1; + } + else if(eed->v2->f1 && !eed->v1->f1){ + eed->v1->f1 = 1; + totnodes++; + unbalanced = 1; + } + } + } + } + + if(s->f1 && t->f1){ /* t can be reached by s */ + Q = MEM_callocN(sizeof(PathNode)*totnodes, "Path Select Nodes"); + totnodes = 0; + for(eve=em->verts.first; eve; eve=eve->next){ + if(eve->f1){ + Q[totnodes].u = totnodes; + Q[totnodes].edges.first = 0; + Q[totnodes].edges.last = 0; + Q[totnodes].visited = 0; + eve->tmp.p = &(Q[totnodes]); + totnodes++; + } + else eve->tmp.p = NULL; + } + + for(eed=em->edges.first; eed; eed=eed->next){ + if(!eed->h){ + if(eed->v1->f1){ + currpn = ((PathNode*)eed->v1->tmp.p); + + newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge"); + newpe->v = ((PathNode*)eed->v2->tmp.p)->u; + if(physical){ + newpe->w = VecLenf(eed->v1->co, eed->v2->co); + } + else newpe->w = 1; + newpe->next = 0; + newpe->prev = 0; + BLI_addtail(&(currpn->edges), newpe); + } + if(eed->v2->f1){ + currpn = ((PathNode*)eed->v2->tmp.p); + newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge"); + newpe->v = ((PathNode*)eed->v1->tmp.p)->u; + if(physical){ + newpe->w = VecLenf(eed->v1->co, eed->v2->co); + } + else newpe->w = 1; + newpe->next = 0; + newpe->prev = 0; + BLI_addtail(&(currpn->edges), newpe); + } + } + } + + heap = BLI_heap_new(); + cost = MEM_callocN(sizeof(float)*totnodes, "Path Select Costs"); + previous = MEM_callocN(sizeof(int)*totnodes, "PathNode indices"); + + for(v=0; v < totnodes; v++){ + cost[v] = 1000000; + previous[v] = -1; /*array of indices*/ + } + + pnindex = ((PathNode*)s->tmp.p)->u; + cost[pnindex] = 0; + BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(pnindex)); + + while( !BLI_heap_empty(heap) ){ + + pnindex = GET_INT_FROM_POINTER(BLI_heap_popmin(heap)); + currpn = &(Q[pnindex]); + + if(currpn == (PathNode*)t->tmp.p) /*target has been reached....*/ + break; + + for(currpe=currpn->edges.first; currpe; currpe=currpe->next){ + if(!Q[currpe->v].visited){ + if( cost[currpe->v] > (cost[currpn->u ] + currpe->w) ){ + cost[currpe->v] = cost[currpn->u] + currpe->w; + previous[currpe->v] = currpn->u; + Q[currpe->v].visited = 1; + BLI_heap_insert(heap, cost[currpe->v], SET_INT_IN_POINTER(currpe->v)); + } + } + } + } + + pathvert = ((PathNode*)t->tmp.p)->u; + while(pathvert != -1){ + for(eve=em->verts.first; eve; eve=eve->next){ + if(eve->f1){ + if( ((PathNode*)eve->tmp.p)->u == pathvert) eve->f |= SELECT; + } + } + pathvert = previous[pathvert]; + } + + for(v=0; v < totnodes; v++) BLI_freelistN(&(Q[v].edges)); + MEM_freeN(Q); + MEM_freeN(cost); + MEM_freeN(previous); + BLI_heap_free(heap, NULL); + EM_select_flush(em); + } + } + else { + BKE_mesh_end_editmesh(obedit->data, em); + BKE_report(op->reports, RPT_ERROR, "Path Selection requires that exactly two vertices be selected"); + return OPERATOR_CANCELLED; + } + + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); + BKE_mesh_end_editmesh(obedit->data, em); +#endif +} + +void MESH_OT_select_vertex_path(wmOperatorType *ot) +{ + static const EnumPropertyItem type_items[] = { + {VPATH_SELECT_EDGE_LENGTH, "EDGE_LENGTH", 0, "Edge Length", NULL}, + {VPATH_SELECT_TOPOLOGICAL, "TOPOLOGICAL", 0, "Topological", NULL}, + {0, NULL, 0, NULL, NULL}}; + + /* identifiers */ + ot->name= "Select Vertex Path"; + ot->idname= "MESH_OT_select_vertex_path"; + + /* api callbacks */ + ot->exec= select_vertex_path_exec; + ot->invoke= WM_menu_invoke; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_enum(ot->srna, "type", type_items, VPATH_SELECT_EDGE_LENGTH, "Type", "Method to compute distance."); +} +/********************** Rip Operator *************************/ + +#if 0 +/* helper for below */ +static void mesh_rip_setface(EditMesh *em, EditFace *sefa) +{ + /* put new vertices & edges in best face */ + if(sefa->v1->tmp.v) sefa->v1= sefa->v1->tmp.v; + if(sefa->v2->tmp.v) sefa->v2= sefa->v2->tmp.v; + if(sefa->v3->tmp.v) sefa->v3= sefa->v3->tmp.v; + if(sefa->v4 && sefa->v4->tmp.v) sefa->v4= sefa->v4->tmp.v; + + sefa->e1= addedgelist(em, sefa->v1, sefa->v2, sefa->e1); + sefa->e2= addedgelist(em, sefa->v2, sefa->v3, sefa->e2); + if(sefa->v4) { + sefa->e3= addedgelist(em, sefa->v3, sefa->v4, sefa->e3); + sefa->e4= addedgelist(em, sefa->v4, sefa->v1, sefa->e4); + } + else + sefa->e3= addedgelist(em, sefa->v3, sefa->v1, sefa->e3); + +} +#endif + +/* helper to find edge for edge_rip */ +static float mesh_rip_edgedist(ARegion *ar, float mat[][4], float *co1, float *co2, short *mval) +{ + float vec1[3], vec2[3], mvalf[2]; + + view3d_project_float(ar, co1, vec1, mat); + view3d_project_float(ar, co2, vec2, mat); + mvalf[0]= (float)mval[0]; + mvalf[1]= (float)mval[1]; + + return PdistVL2Dfl(mvalf, vec1, vec2); +} + +/* based on mouse cursor position, it defines how is being ripped */ +static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + Object *obedit= CTX_data_edit_object(C); + ARegion *ar= CTX_wm_region(C); + RegionView3D *rv3d= CTX_wm_region_view3d(C); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; + BMOperator bmop; + BMBVHTree *bvhtree; + BMOIter siter; + BMIter iter, eiter, liter; + BMLoop *l; + BMEdge *e, *e2, *closest = NULL; + BMVert *v; + int side = 0, i; + float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1], 0.0f}; + float dist = FLT_MAX, d; + + view3d_get_object_project_mat(rv3d, obedit, projectMat); + + BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) { + if (BM_TestHFlag(e, BM_SELECT)) + BMINDEX_SET(e, 1); + else BMINDEX_SET(e, 0); + } + + /*handle case of one vert selected. we identify + the closest edge around that vert to the mouse cursor, + then rip the two adjacent edges in the vert fan.*/ + if (em->bm->totvertsel == 1 && em->bm->totedgesel == 0 && em->bm->totfacesel == 0) { + /*find selected vert*/ + BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + if (BM_TestHFlag(v, BM_SELECT)) + break; + } + + /*this should be impossible, but sanity checks are a good thing*/ + if (!v) + return OPERATOR_CANCELLED; + + /*find closest edge to mouse cursor*/ + e2 = NULL; + BM_ITER(e, &iter, em->bm, BM_EDGES_OF_VERT, v) { + d = mesh_rip_edgedist(ar, projectMat, e->v1->co, e->v2->co, event->mval); + if (d < dist) { + dist = d; + e2 = e; + } + } + + if (!e2) + return OPERATOR_CANCELLED; + + /*rip two adjacent edges*/ + if (BM_Edge_FaceCount(e2) == 1) { + l = e2->loop; + e = BM_OtherFaceLoop(e2, l->f, v); + + BMINDEX_SET(e, 1); + BM_SetHFlag(e, BM_SELECT); + } else if (BM_Edge_FaceCount(e2) == 2) { + l = e2->loop; + e = BM_OtherFaceLoop(e2, l->f, v); + BMINDEX_SET(e, 1); + BM_SetHFlag(e, BM_SELECT); + + l = e2->loop->radial.next->data; + e = BM_OtherFaceLoop(e2, l->f, v); + BMINDEX_SET(e, 1); + BM_SetHFlag(e, BM_SELECT); + } + } else { + /*expand edge selection*/ + BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + e2 = NULL; + i = 0; + BM_ITER(e, &eiter, em->bm, BM_EDGES_OF_VERT, v) { + if (BMINDEX_GET(e)) { + e2 = e; + i++; + } + } + + if (i == 1 && e2->loop) { + l = BM_OtherFaceLoop(e2, e2->loop->f, v); + l = (BMLoop*)l->radial.next->data; + l = BM_OtherFaceLoop(l->e, l->f, v); + + if (l) + BM_Select(em->bm, l->e, 1); + } + } + } + + if (!EDBM_InitOpf(em, &bmop, op, "edgesplit edges=%he", BM_SELECT)) { + return OPERATOR_CANCELLED; + } + + BMO_Exec_Op(em->bm, &bmop); + + /*build bvh tree for edge visibility tests*/ + bvhtree = BMBVH_NewBVH(em); + + for (i=0; i<2; i++) { + BMO_ITER(e, &siter, em->bm, &bmop, i ? "edgeout2":"edgeout1", BM_EDGE) { + float cent[3] = {0, 0, 0}, mid[4], vec[3]; + + if (!BMBVH_EdgeVisible(bvhtree, e, rv3d, obedit)) + continue; + + /*method for calculating distance: + + for each edge: calculate face center, then made a vector + from edge midpoint to face center. offset edge midpoint + by a small amount along this vector.*/ + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, e->loop->f) { + VecAddf(cent, cent, l->v->co); + } + VecMulf(cent, 1.0f/(float)e->loop->f->len); + + VecAddf(mid, e->v1->co, e->v2->co); + VecMulf(mid, 0.5f); + VecSubf(vec, cent, mid); + Normalize(vec); + VecMulf(vec, 0.01f); + VecAddf(mid, mid, vec); + + /*yay we have our comparison point, now project it*/ + view3d_project_float(ar, mid, mid, projectMat); + + vec[0] = fmval[0] - mid[0]; + vec[1] = fmval[1] - mid[1]; + d = vec[0]*vec[0] + vec[1]*vec[1]; + + if (d < dist) { + side = i; + closest = e; + dist = d; + } + } + } + + EDBM_clear_flag_all(em, BM_SELECT); + BMO_HeaderFlag_Buffer(em->bm, &bmop, side?"edgeout2":"edgeout1", BM_SELECT, BM_EDGE); + + BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) { + if (BM_TestHFlag(e, BM_SELECT)) + BMINDEX_SET(e, 1); + else BMINDEX_SET(e, 0); + } + + /*constrict edge selection again*/ + BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + e2 = NULL; + i = 0; + BM_ITER(e, &eiter, em->bm, BM_EDGES_OF_VERT, v) { + if (BMINDEX_GET(e)) { + e2 = e; + i++; + } + } + + if (i == 1) + BM_Select(em->bm, e2, 0); + } + + EDBM_selectmode_flush(em); + + if (!EDBM_FinishOp(em, &bmop, op, 1)) { + BMBVH_FreeBVH(bvhtree); + return OPERATOR_CANCELLED; + } + + BMBVH_FreeBVH(bvhtree); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +#if 0 //BMESH_TODO + ARegion *ar= CTX_wm_region(C); + RegionView3D *rv3d= ar->regiondata; + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + EditVert *eve, *nextve; + EditEdge *eed, *seed= NULL; + EditFace *efa, *sefa= NULL; + float projectMat[4][4], vec[3], dist, mindist; + short doit= 1, *mval= event->mval; + + /* select flush... vertices are important */ + EM_selectmode_set(em); + + view3d_get_object_project_mat(rv3d, obedit, projectMat); + + /* find best face, exclude triangles and break on face select or faces with 2 edges select */ + mindist= 1000000.0f; + for(efa= em->faces.first; efa; efa=efa->next) { + if( efa->f & 1) + break; + if(efa->v4 && faceselectedOR(efa, SELECT) ) { + int totsel=0; + + if(efa->e1->f & SELECT) totsel++; + if(efa->e2->f & SELECT) totsel++; + if(efa->e3->f & SELECT) totsel++; + if(efa->e4->f & SELECT) totsel++; + + if(totsel>1) + break; + view3d_project_float(ar, efa->cent, vec, projectMat); + dist= sqrt( (vec[0]-mval[0])*(vec[0]-mval[0]) + (vec[1]-mval[1])*(vec[1]-mval[1]) ); + if(dist<mindist) { + mindist= dist; + sefa= efa; + } + } + } + + if(efa) { + BKE_report(op->reports, RPT_ERROR, "Can't perform ripping with faces selected this way"); + BKE_mesh_end_editmesh(obedit->data, em); + return OPERATOR_CANCELLED; + } + if(sefa==NULL) { + BKE_report(op->reports, RPT_ERROR, "No proper selection or faces included"); + BKE_mesh_end_editmesh(obedit->data, em); + return OPERATOR_CANCELLED; + } + + + /* duplicate vertices, new vertices get selected */ + for(eve = em->verts.last; eve; eve= eve->prev) { + eve->tmp.v = NULL; + if(eve->f & SELECT) { + eve->tmp.v = addvertlist(em, eve->co, eve); + eve->f &= ~SELECT; + eve->tmp.v->f |= SELECT; + } + } + + /* find the best candidate edge */ + /* or one of sefa edges is selected... */ + if(sefa->e1->f & SELECT) seed= sefa->e2; + if(sefa->e2->f & SELECT) seed= sefa->e1; + if(sefa->e3->f & SELECT) seed= sefa->e2; + if(sefa->e4 && sefa->e4->f & SELECT) seed= sefa->e3; + + /* or we do the distance trick */ + if(seed==NULL) { + mindist= 1000000.0f; + if(sefa->e1->v1->tmp.v || sefa->e1->v2->tmp.v) { + dist = mesh_rip_edgedist(ar, projectMat, + sefa->e1->v1->co, + sefa->e1->v2->co, mval); + if(dist<mindist) { + seed= sefa->e1; + mindist= dist; + } + } + if(sefa->e2->v1->tmp.v || sefa->e2->v2->tmp.v) { + dist = mesh_rip_edgedist(ar, projectMat, + sefa->e2->v1->co, + sefa->e2->v2->co, mval); + if(dist<mindist) { + seed= sefa->e2; + mindist= dist; + } + } + if(sefa->e3->v1->tmp.v || sefa->e3->v2->tmp.v) { + dist= mesh_rip_edgedist(ar, projectMat, + sefa->e3->v1->co, + sefa->e3->v2->co, mval); + if(dist<mindist) { + seed= sefa->e3; + mindist= dist; + } + } + if(sefa->e4 && (sefa->e4->v1->tmp.v || sefa->e4->v2->tmp.v)) { + dist= mesh_rip_edgedist(ar, projectMat, + sefa->e4->v1->co, + sefa->e4->v2->co, mval); + if(dist<mindist) { + seed= sefa->e4; + mindist= dist; + } + } + } + + if(seed==NULL) { // never happens? + BKE_report(op->reports, RPT_ERROR, "No proper edge found to start"); + BKE_mesh_end_editmesh(obedit->data, em); + return OPERATOR_CANCELLED; + } + + faceloop_select(em, seed, 2); // tmp abuse for finding all edges that need duplicated, returns OK faces with f1 + + /* duplicate edges in the loop, with at least 1 vertex selected, needed for selection flip */ + for(eed = em->edges.last; eed; eed= eed->prev) { + eed->tmp.v = NULL; + if((eed->v1->tmp.v) || (eed->v2->tmp.v)) { + EditEdge *newed; + + newed= addedgelist(em, eed->v1->tmp.v?eed->v1->tmp.v:eed->v1, + eed->v2->tmp.v?eed->v2->tmp.v:eed->v2, eed); + if(eed->f & SELECT) { + EM_select_edge(eed, 0); + EM_remove_selection(em, eed, EDITEDGE); + EM_select_edge(newed, 1); + } + eed->tmp.v = (EditVert *)newed; + } + } + + /* first clear edges to help finding neighbours */ + for(eed = em->edges.last; eed; eed= eed->prev) eed->f1= 0; + + /* put new vertices & edges && flag in best face */ + mesh_rip_setface(em, sefa); + + /* starting with neighbours of best face, we loop over the seam */ + sefa->f1= 2; + doit= 1; + while(doit) { + doit= 0; + + for(efa= em->faces.first; efa; efa=efa->next) { + /* new vert in face */ + if (efa->v1->tmp.v || efa->v2->tmp.v || + efa->v3->tmp.v || (efa->v4 && efa->v4->tmp.v)) { + /* face is tagged with loop */ + if(efa->f1==1) { + mesh_rip_setface(em, efa); + efa->f1= 2; + doit= 1; + } + } + } + } + + /* remove loose edges, that were part of a ripped face */ + for(eve = em->verts.first; eve; eve= eve->next) eve->f1= 0; + for(eed = em->edges.last; eed; eed= eed->prev) eed->f1= 0; + for(efa= em->faces.first; efa; efa=efa->next) { + efa->e1->f1= 1; + efa->e2->f1= 1; + efa->e3->f1= 1; + if(efa->e4) efa->e4->f1= 1; + } + + for(eed = em->edges.last; eed; eed= seed) { + seed= eed->prev; + if(eed->f1==0) { + if(eed->v1->tmp.v || eed->v2->tmp.v || + (eed->v1->f & SELECT) || (eed->v2->f & SELECT)) { + remedge(em, eed); + free_editedge(em, eed); + eed= NULL; + } + } + if(eed) { + eed->v1->f1= 1; + eed->v2->f1= 1; + } + } + + /* and remove loose selected vertices, that got duplicated accidentally */ + for(eve = em->verts.first; eve; eve= nextve) { + nextve= eve->next; + if(eve->f1==0 && (eve->tmp.v || (eve->f & SELECT))) { + BLI_remlink(&em->verts,eve); + free_editvert(em, eve); + } + } + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + BKE_mesh_end_editmesh(obedit->data, em); + +// RNA_enum_set(op->ptr, "proportional", 0); +// RNA_boolean_set(op->ptr, "mirror", 0); +// WM_operator_name_call(C, "TFM_OT_translate", WM_OP_INVOKE_REGION_WIN, op->ptr); +#endif +} + +void MESH_OT_rip(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Rip"; + ot->idname= "MESH_OT_rip"; + + /* api callbacks */ + ot->invoke= mesh_rip_invoke; + ot->poll= EM_view3d_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* to give to transform */ + Properties_Proportional(ot); + RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", ""); +}
\ No newline at end of file diff --git a/source/blender/editors/mesh/bmeshutils.c b/source/blender/editors/mesh/bmeshutils.c new file mode 100644 index 00000000000..bf7889ef3c0 --- /dev/null +++ b/source/blender/editors/mesh/bmeshutils.c @@ -0,0 +1,784 @@ + /* $Id: bmeshutils.c + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2004 by Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joseph Eagar + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <math.h> +#include <float.h> + +#include "MEM_guardedalloc.h" +#include "PIL_time.h" + +#include "BLO_sys_types.h" // for intptr_t support + +#include "DNA_mesh_types.h" +#include "DNA_material_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_view3d_types.h" +#include "DNA_key_types.h" +#include "DNA_windowmanager_types.h" + +#include "RNA_types.h" +#include "RNA_define.h" +#include "RNA_access.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_editVert.h" +#include "BLI_rand.h" +#include "BLI_ghash.h" +#include "BLI_linklist.h" +#include "BLI_heap.h" +#include "BLI_array.h" + +#include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_depsgraph.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" +#include "BKE_bmesh.h" +#include "BKE_report.h" +#include "BKE_tessmesh.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_mesh.h" +#include "ED_view3d.h" +#include "ED_util.h" +#include "ED_screen.h" + +#include "UI_interface.h" + +#include "mesh_intern.h" +#include "bmesh.h" + +void EDBM_RecalcNormals(BMEditMesh *em) +{ + BM_Compute_Normals(em->bm); +} + +void EDBM_stats_update(BMEditMesh *em) +{ + BMIter iter; + BMHeader *ele; + int types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH}; + int *tots[3]; + int i; + + tots[0] = &em->bm->totvertsel; + tots[1] = &em->bm->totedgesel; + tots[2] = &em->bm->totfacesel; + + em->bm->totvertsel = em->bm->totedgesel = em->bm->totfacesel = 0; + + for (i=0; i<3; i++) { + ele = BMIter_New(&iter, em->bm, types[i], NULL); + for ( ; ele; ele=BMIter_Step(&iter)) { + if (BM_TestHFlag(ele, BM_SELECT)) { + *tots[i]++; + } + } + } +} + +/*this function is defunct, dead*/ +void EDBM_Tesselate(EditMesh *em) +{ + EditMesh *em2; + EditFace *efa; + BMesh *bm; + int found=0; + + for (efa=em->faces.first; efa; efa=efa->next) { + if ((efa->e1->h & EM_FGON) || (efa->e2->h & EM_FGON) || + (efa->e3->h & EM_FGON) || (efa->e4&&(efa->e4->h&EM_FGON))) + { + found = 1; + break; + } + } + + if (found) { + bm = editmesh_to_bmesh(em); + em2 = bmesh_to_editmesh(bm); + set_editMesh(em, em2); + + MEM_freeN(em2); + BM_Free_Mesh(bm); + } +} + +int EDBM_InitOpf(BMEditMesh *em, BMOperator *bmop, wmOperator *op, char *fmt, ...) +{ + BMesh *bm = em->bm; + va_list list; + + va_start(list, fmt); + + if (!BMO_VInitOpf(bm, bmop, fmt, list)) { + BKE_report(op->reports, RPT_ERROR, + "Parse error in EDBM_CallOpf"); + va_end(list); + return 0; + } + + if (!em->emcopy) + em->emcopy = BMEdit_Copy(em); + em->emcopyusers++; + + va_end(list); +} + + +/*returns 0 on error, 1 on success. executes and finishes a bmesh operator*/ +int EDBM_FinishOp(BMEditMesh *em, BMOperator *bmop, wmOperator *op, int report) { + char *errmsg; + + BMO_Finish_Op(em->bm, bmop); + + if (BMO_GetError(em->bm, &errmsg, NULL)) { + BMEditMesh *emcopy = em->emcopy; + + if (report) BKE_report(op->reports, RPT_ERROR, errmsg); + + BMEdit_Free(em); + *em = *emcopy; + + MEM_freeN(emcopy); + em->emcopyusers = 0; + em->emcopy = NULL; + return 0; + } else { + em->emcopyusers--; + if (em->emcopyusers < 0) { + printf("warning: em->emcopyusers was less then zero.\n"); + } + + if (em->emcopyusers <= 0) { + BMEdit_Free(em->emcopy); + MEM_freeN(em->emcopy); + em->emcopy = NULL; + } + } + + return 1; +} + +int EDBM_CallOpf(BMEditMesh *em, wmOperator *op, char *fmt, ...) +{ + BMesh *bm = em->bm; + BMOperator bmop; + va_list list; + + va_start(list, fmt); + + if (!BMO_VInitOpf(bm, &bmop, fmt, list)) { + BKE_report(op->reports, RPT_ERROR, + "Parse error in EDBM_CallOpf"); + va_end(list); + return 0; + } + + if (!em->emcopy) + em->emcopy = BMEdit_Copy(em); + em->emcopyusers++; + + BMO_Exec_Op(bm, &bmop); + + va_end(list); + return EDBM_FinishOp(em, &bmop, op, 1); +} + +int EDBM_CallOpfSilent(BMEditMesh *em, char *fmt, ...) +{ + BMesh *bm = em->bm; + BMOperator bmop; + va_list list; + + va_start(list, fmt); + + if (!BMO_VInitOpf(bm, &bmop, fmt, list)) { + va_end(list); + return 0; + } + + if (!em->emcopy) + em->emcopy = BMEdit_Copy(em); + em->emcopyusers++; + + BMO_Exec_Op(bm, &bmop); + + va_end(list); + return EDBM_FinishOp(em, &bmop, NULL, 0); +} + +void EDBM_MakeEditBMesh(ToolSettings *ts, Scene *scene, Object *ob) +{ + Mesh *me = ob->data; + EditMesh *em; + BMesh *bm; + + if (!me->mpoly && me->totface) { + em = make_editMesh(scene, ob); + bm = editmesh_to_bmesh(em); + + free_editMesh(em); + } else { + bm = BKE_mesh_to_bmesh(me); + } + + me->edit_btmesh = BMEdit_Create(bm); + me->edit_btmesh->selectmode = ts->selectmode; +} + +void EDBM_LoadEditBMesh(Scene *scene, Object *ob) +{ + Mesh *me = ob->data; + BMesh *bm = me->edit_btmesh->bm; + + BMO_CallOpf(bm, "object_load_bmesh scene=%p object=%p", scene, ob); +} + +void EDBM_FreeEditBMesh(BMEditMesh *tm) +{ + BMEdit_Free(tm); +} + +void EDBM_init_index_arrays(BMEditMesh *tm, int forvert, int foredge, int forface) +{ + EDBM_free_index_arrays(tm); + + if (forvert) { + BMIter iter; + BMVert *ele; + int i=0; + + tm->vert_index = MEM_mallocN(sizeof(void**)*tm->bm->totvert, "tm->vert_index"); + + ele = BMIter_New(&iter, tm->bm, BM_VERTS_OF_MESH, NULL); + for ( ; ele; ele=BMIter_Step(&iter)) { + tm->vert_index[i++] = ele; + } + } + + if (foredge) { + BMIter iter; + BMEdge *ele; + int i=0; + + tm->edge_index = MEM_mallocN(sizeof(void**)*tm->bm->totedge, "tm->edge_index"); + + ele = BMIter_New(&iter, tm->bm, BM_EDGES_OF_MESH, NULL); + for ( ; ele; ele=BMIter_Step(&iter)) { + tm->edge_index[i++] = ele; + } + } + + if (forface) { + BMIter iter; + BMFace *ele; + int i=0; + + tm->face_index = MEM_mallocN(sizeof(void**)*tm->bm->totface, "tm->face_index"); + + ele = BMIter_New(&iter, tm->bm, BM_FACES_OF_MESH, NULL); + for ( ; ele; ele=BMIter_Step(&iter)) { + tm->face_index[i++] = ele; + } + } +} + +void EDBM_free_index_arrays(BMEditMesh *tm) +{ + if (tm->vert_index) { + MEM_freeN(tm->vert_index); + tm->vert_index = NULL; + } + + if (tm->edge_index) { + MEM_freeN(tm->edge_index); + tm->edge_index = NULL; + } + + if (tm->face_index) { + MEM_freeN(tm->face_index); + tm->face_index = NULL; + } +} + +BMVert *EDBM_get_vert_for_index(BMEditMesh *tm, int index) +{ + return tm->vert_index?tm->vert_index[index]:NULL; +} + +BMEdge *EDBM_get_edge_for_index(BMEditMesh *tm, int index) +{ + return tm->edge_index?tm->edge_index[index]:NULL; +} + +BMFace *EDBM_get_face_for_index(BMEditMesh *tm, int index) +{ + return tm->face_index?tm->face_index[index]:NULL; +} + +/* this replaces the active flag used in uv/face mode */ +void EDBM_set_actFace(BMEditMesh *em, BMFace *efa) +{ + em->bm->act_face = efa; +} + +BMFace *EDBM_get_actFace(BMEditMesh *em, int sloppy) +{ + if (em->bm->act_face) { + return em->bm->act_face; + } else if (sloppy) { + BMFace *efa= NULL; + BMEditSelection *ese; + + ese = em->bm->selected.last; + for (; ese; ese=ese->prev){ + if(ese->type == BM_FACE) { + efa = (BMFace *)ese->data; + + if (BM_TestHFlag(efa, BM_HIDDEN)) efa= NULL; + else break; + } + } + if (efa==NULL) { + BMIter iter; + efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL); + for ( ; efa; efa=BMIter_Step(&iter)) { + if (BM_TestHFlag(efa, BM_SELECT)) + break; + } + } + return efa; /* can still be null */ + } + return NULL; + +} + +void EDBM_select_flush(BMEditMesh *em, int selectmode) +{ + em->bm->selectmode = selectmode; + BM_SelectMode_Flush(em->bm); + em->bm->selectmode = em->selectmode; +} + +/*BMESH_TODO*/ +void EDBM_deselect_flush(BMEditMesh *em) +{ +} + + +void EDBM_selectmode_flush(BMEditMesh *em) +{ + em->bm->selectmode = em->selectmode; + BM_SelectMode_Flush(em->bm); +} + +/*EDBM_select_[more/less] are api functions, I think the uv editor + uses them? though the select more/less ops themselves do not.*/ +void EDBM_select_more(BMEditMesh *em) +{ + BMOperator bmop; + int usefaces = em->selectmode > SCE_SELECT_EDGE; + + BMO_InitOpf(em->bm, &bmop, + "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, BM_ALL); + BMO_Finish_Op(em->bm, &bmop); + + EDBM_selectmode_flush(em); +} + +void EDBM_select_less(BMEditMesh *em) +{ + BMOperator bmop; + int usefaces = em->selectmode > SCE_SELECT_EDGE; + + BMO_InitOpf(em->bm, &bmop, + "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, BM_ALL); + BMO_Finish_Op(em->bm, &bmop); + + EDBM_selectmode_flush(em); +} + +int EDBM_get_actSelection(BMEditMesh *em, BMEditSelection *ese) +{ + BMEditSelection *ese_last = em->bm->selected.last; + BMFace *efa = EDBM_get_actFace(em, 0); + + ese->next = ese->prev = NULL; + + if (ese_last) { + if (ese_last->type == BM_FACE) { /* if there is an active face, use it over the last selected face */ + if (efa) { + ese->data = (void *)efa; + } else { + ese->data = ese_last->data; + } + ese->type = BM_FACE; + } else { + ese->data = ese_last->data; + ese->type = ese_last->type; + } + } else if (efa) { /* no */ + ese->data = (void *)efa; + ese->type = BM_FACE; + } else { + ese->data = NULL; + return 0; + } + return 1; +} + +void EDBM_clear_flag_all(BMEditMesh *em, int flag) +{ + BMIter iter; + BMHeader *ele; + int i, type; + + if (flag & BM_SELECT) + BM_clear_selection_history(em->bm); + + for (i=0; i<3; i++) { + switch (i) { + case 0: + type = BM_VERTS_OF_MESH; + break; + case 1: + type = BM_EDGES_OF_MESH; + break; + case 2: + type = BM_FACES_OF_MESH; + break; + } + + ele = BMIter_New(&iter, em->bm, type, NULL); + for ( ; ele; ele=BMIter_Step(&iter)) { + if (flag & BM_SELECT) BM_Select(em->bm, ele, 0); + BM_ClearHFlag(ele, flag); + } + } +} + +void EDBM_set_flag_all(BMEditMesh *em, int flag) +{ + BMIter iter; + BMHeader *ele; + int i, type; + + for (i=0; i<3; i++) { + switch (i) { + case 0: + type = BM_VERTS_OF_MESH; + break; + case 1: + type = BM_EDGES_OF_MESH; + break; + case 2: + type = BM_FACES_OF_MESH; + break; + } + + ele = BMIter_New(&iter, em->bm, type, NULL); + for ( ; ele; ele=BMIter_Step(&iter)) { + if (flag & BM_SELECT) BM_Select(em->bm, ele, 1); + BM_SetHFlag(ele, flag); + } + } +} + +/**************-------------- Undo ------------*****************/ + +/* for callbacks */ + +static void *getEditMesh(bContext *C) +{ + Object *obedit= CTX_data_edit_object(C); + if(obedit && obedit->type==OB_MESH) { + Mesh *me= obedit->data; + return me->edit_btmesh; + } + return NULL; +} + +typedef struct undomesh { + Mesh me; + int selectmode; +} undomesh; + +/*undo simply makes copies of a bmesh*/ +static void *editbtMesh_to_undoMesh(void *emv) +{ + BMEditMesh *em = emv; + undomesh *me = MEM_callocN(sizeof(undomesh), "undo Mesh"); + + /*we recalc the tesselation here, to avoid seeding calls to + BMEdit_RecalcTesselation throughout the code.*/ + BMEdit_RecalcTesselation(em); + + BMO_CallOpf(em->bm, "bmesh_to_mesh meshptr=%p notesselation=%i", me, 1); + me->selectmode = em->selectmode; + + return me; +} + +static void undoMesh_to_editbtMesh(void *umv, void *emv) +{ + BMEditMesh *em = emv, *em2; + undomesh *me = umv; + BMesh *bm; + int allocsize[4] = {512, 512, 2048, 512}; + + BMEdit_Free(em); + + bm = BM_Make_Mesh(allocsize); + BMO_CallOpf(bm, "mesh_to_bmesh mesh=%p", me); + + em2 = BMEdit_Create(bm); + *em = *em2; + + em->selectmode = me->selectmode; + + MEM_freeN(em2); +} + + +static void free_undo(void *umv) +{ + free_mesh(umv, 0); + MEM_freeN(umv); +} + +/* and this is all the undo system needs to know */ +void undo_push_mesh(bContext *C, char *name) +{ + undo_editmode_push(C, name, getEditMesh, free_undo, undoMesh_to_editbtMesh, editbtMesh_to_undoMesh, NULL); +} + +/*write comment here*/ +UvVertMap *EDBM_make_uv_vert_map(BMEditMesh *em, int selected, int do_face_idx_array, float *limit) +{ + BMVert *ev; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + /* vars from original func */ + UvVertMap *vmap; + UvMapVert *buf; + MTexPoly *tf; + MLoopUV *luv; + unsigned int a; + int totverts, i, totuv; + + if (do_face_idx_array) + EDBM_init_index_arrays(em, 0, 0, 1); + + /* we need the vert */ + totverts=0; + BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + BMINDEX_SET(ev, totverts); + totverts++; + } + + totuv = 0; + + /* generate UvMapVert array */ + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if(!selected || ((!BM_TestHFlag(efa, BM_HIDDEN)) && BM_TestHFlag(efa, BM_SELECT))) + totuv += efa->len; + } + + if(totuv==0) { + if (do_face_idx_array) + EDBM_free_index_arrays(em); + return NULL; + } + vmap= (UvVertMap*)MEM_callocN(sizeof(*vmap), "UvVertMap"); + if (!vmap) { + if (do_face_idx_array) + EDBM_free_index_arrays(em); + return NULL; + } + + vmap->vert= (UvMapVert**)MEM_callocN(sizeof(*vmap->vert)*totverts, "UvMapVert*"); + buf= vmap->buf= (UvMapVert*)MEM_callocN(sizeof(*vmap->buf)*totuv, "UvMapVert"); + + if (!vmap->vert || !vmap->buf) { + free_uv_vert_map(vmap); + if (do_face_idx_array) + EDBM_free_index_arrays(em); + return NULL; + } + + a = 0; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if(!selected || ((!BM_TestHFlag(efa, BM_HIDDEN)) && BM_TestHFlag(efa, BM_SELECT))) { + i = 0; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + buf->tfindex= i; + buf->f= a; + buf->separate = 0; + + buf->next= vmap->vert[BMINDEX_GET(l->v)]; + vmap->vert[BMINDEX_GET(l->v)]= buf; + + buf++; + i++; + } + } + + a++; + } + + /* sort individual uvs for each vert */ + a = 0; + BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + UvMapVert *newvlist= NULL, *vlist=vmap->vert[a]; + UvMapVert *iterv, *v, *lastv, *next; + float *uv, *uv2, uvdiff[2]; + + while(vlist) { + v= vlist; + vlist= vlist->next; + v->next= newvlist; + newvlist= v; + + efa = EDBM_get_face_for_index(em, v->f); + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + + l = BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa, v->tfindex); + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + uv = luv->uv; + + lastv= NULL; + iterv= vlist; + + while(iterv) { + next= iterv->next; + efa = EDBM_get_face_for_index(em, iterv->f); + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + + l = BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex); + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + uv2 = luv->uv; + + Vec2Subf(uvdiff, uv2, uv); + + if(fabs(uv[0]-uv2[0]) < limit[0] && fabs(uv[1]-uv2[1]) < limit[1]) { + if(lastv) lastv->next= next; + else vlist= next; + iterv->next= newvlist; + newvlist= iterv; + } + else + lastv=iterv; + + iterv= next; + } + + newvlist->separate = 1; + } + + vmap->vert[a]= newvlist; + a++; + } + + if (do_face_idx_array) + EDBM_free_index_arrays(em); + + return vmap; +} + + +UvMapVert *EDBM_get_uv_map_vert(UvVertMap *vmap, unsigned int v) +{ + return vmap->vert[v]; +} + +void EDBM_free_uv_vert_map(UvVertMap *vmap) +{ + if (vmap) { + if (vmap->vert) MEM_freeN(vmap->vert); + if (vmap->buf) MEM_freeN(vmap->buf); + MEM_freeN(vmap); + } +} + + +/* last_sel, use em->act_face otherwise get the last selected face in the editselections + * at the moment, last_sel is mainly useful for gaking sure the space image dosnt flicker */ +MTexPoly *EDBM_get_active_mtexpoly(BMEditMesh *em, BMFace **act_efa, int sloppy) +{ + BMFace *efa = NULL; + + if(!EDBM_texFaceCheck(em)) + return NULL; + + efa = EDBM_get_actFace(em, sloppy); + + if (efa) { + if (act_efa) *act_efa = efa; + return CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + } + + if (act_efa) *act_efa= NULL; + return NULL; +} + +/* can we edit UV's for this mesh?*/ +int EDBM_texFaceCheck(BMEditMesh *em) +{ + /* some of these checks could be a touch overkill */ + return em && em->bm->totface && CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY); +} + +int EDBM_vertColorCheck(BMEditMesh *em) +{ + /* some of these checks could be a touch overkill */ + return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPCOL); +} + diff --git a/source/blender/editors/mesh/editbmesh_bvh.c b/source/blender/editors/mesh/editbmesh_bvh.c new file mode 100644 index 00000000000..d93100e3740 --- /dev/null +++ b/source/blender/editors/mesh/editbmesh_bvh.c @@ -0,0 +1,288 @@ + /* $Id: + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2004 by Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joseph Eagar + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <math.h> +#include <float.h> + +#include "MEM_guardedalloc.h" +#include "PIL_time.h" + +#include "BLO_sys_types.h" // for intptr_t support + +#include "DNA_mesh_types.h" +#include "DNA_material_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_view3d_types.h" +#include "DNA_key_types.h" +#include "DNA_windowmanager_types.h" + +#include "RNA_types.h" +#include "RNA_define.h" +#include "RNA_access.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_editVert.h" +#include "BLI_rand.h" +#include "BLI_ghash.h" +#include "BLI_linklist.h" +#include "BLI_heap.h" +#include "BLI_array.h" +#include "BLI_kdopbvh.h" + +#include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_depsgraph.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" +#include "BKE_bmesh.h" +#include "BKE_report.h" +#include "BKE_tessmesh.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_mesh.h" +#include "ED_view3d.h" +#include "ED_util.h" +#include "ED_screen.h" +#include "ED_transform.h" + +#include "UI_interface.h" + +#include "mesh_intern.h" +#include "bmesh.h" + +#include "editbmesh_bvh.h" + +typedef struct BMBVHTree { + BMEditMesh *em; + BMesh *bm; + BVHTree *tree; + float epsilon; +} BMBVHTree; + +BMBVHTree *BMBVH_NewBVH(BMEditMesh *em) +{ + BMBVHTree *tree = MEM_callocN(sizeof(*tree), "BMBVHTree"); + float cos[3][3]; + int i; + + BMEdit_RecalcTesselation(em); + + tree->em = em; + tree->bm = em->bm; + tree->epsilon = FLT_EPSILON*2.0f; + + tree->tree = BLI_bvhtree_new(em->tottri, tree->epsilon, 8, 8); + + for (i=0; i<em->tottri; i++) { + VECCOPY(cos[0], em->looptris[i][0]->v->co); + VECCOPY(cos[1], em->looptris[i][1]->v->co); + VECCOPY(cos[2], em->looptris[i][2]->v->co); + + BLI_bvhtree_insert(tree->tree, i, (float*)cos, 3); + } + + BLI_bvhtree_balance(tree->tree); + + return tree; +} + +void BMBVH_FreeBVH(BMBVHTree *tree) +{ + BLI_bvhtree_free(tree->tree); + MEM_freeN(tree); +} + +/*taken from bvhutils.c*/ +static float ray_tri_intersection(const BVHTreeRay *ray, const float m_dist, float *v0, + float *v1, float *v2, float *uv, float e) +{ + float dist; +#if 0 + float vv1[3], vv2[3], vv3[3], cent[3]; + + /*expand triangle by an epsilon. this is probably a really stupid + way of doing it, but I'm too tired to do better work.*/ + VECCOPY(vv1, v0); + VECCOPY(vv2, v1); + VECCOPY(vv3, v2); + + VecAddf(cent, vv1, vv2); + VecAddf(cent, cent, vv3); + VecMulf(cent, 1.0f/3.0f); + + VecSubf(vv1, vv1, cent); + VecSubf(vv2, vv2, cent); + VecSubf(vv3, vv3, cent); + + VecMulf(vv1, 1.0f + e); + VecMulf(vv2, 1.0f + e); + VecMulf(vv3, 1.0f + e); + + VecAddf(vv1, vv1, cent); + VecAddf(vv2, vv2, cent); + VecAddf(vv3, vv3, cent); + + if(RayIntersectsTriangle((float*)ray->origin, (float*)ray->direction, vv1, vv2, vv3, &dist, uv)) + return dist; +#else + if(RayIntersectsTriangle((float*)ray->origin, (float*)ray->direction, v0, v1, v2, &dist, uv)) + return dist; +#endif + + return FLT_MAX; +} + +static void raycallback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) +{ + BMBVHTree *tree = userdata; + BMLoop **ls = tree->em->looptris[index]; + float dist, uv[2], co1[3], co2[3], co3[3]; + + dist = ray_tri_intersection(ray, hit->dist, ls[0]->v->co, ls[1]->v->co, + ls[2]->v->co, uv, tree->epsilon); + if (dist < hit->dist) { + hit->dist = dist; + hit->index = index; + + VECCOPY(hit->no, ls[0]->v->no); + + VECCOPY(co1, ls[0]->v->co); + VECCOPY(co2, ls[1]->v->co); + VECCOPY(co3, ls[2]->v->co); + + VecMulf(co1, uv[0]); + VecMulf(co2, uv[1]); + VecMulf(co3, 1.0f-uv[0]-uv[1]); + + VecAddf(hit->co, co1, co2); + VecAddf(hit->co, hit->co, co3); + } +} + +BMFace *BMBVH_RayCast(BMBVHTree *tree, float *co, float *dir, float *hitout) +{ + BVHTreeRayHit hit; + + hit.dist = FLT_MAX; + hit.index = -1; + + BLI_bvhtree_ray_cast(tree->tree, co, dir, FLT_MAX, &hit, raycallback, tree); + if (hit.dist != FLT_MAX && hit.index != -1) { + if (hitout) { + VECCOPY(hitout, hit.co); + } + + return tree->em->looptris[hit.index][0]->f; + } + + return NULL; +} + +#if 0 //BMESH_TODO: not implemented yet +int BMBVH_VertVisible(BMBVHTree *tree, BMEdge *e, RegionView3D *r3d) +{ + +} +#endif + +static BMFace *edge_ray_cast(BMBVHTree *tree, float *co, float *dir, float *hitout, BMEdge *e) +{ + BMFace *f = BMBVH_RayCast(tree, co, dir, hitout); + + if (f && BM_Edge_In_Face(f, e)) + return NULL; + + return f; +} + +int BMBVH_EdgeVisible(BMBVHTree *tree, BMEdge *e, RegionView3D *r3d, Object *obedit) +{ + BMFace *f; + float co1[3], co2[3], co3[3], dir1[4], dir2[4], dir3[4]; + float origin[3], invmat[4][4]; + float epsilon = 0.01f; + + VECCOPY(origin, r3d->viewinv[3]); + Mat4Invert(invmat, obedit->obmat); + Mat4MulVecfl(invmat, origin); + + VECCOPY(co1, e->v1->co); + VecAddf(co2, e->v1->co, e->v2->co); + VecMulf(co2, 0.5f); + VECCOPY(co3, e->v2->co); + + /*ok, idea is to generate rays going from the camera origin to the + three points on the edge (v1, mid, v2)*/ + VecSubf(dir1, origin, co1); + VecSubf(dir2, origin, co2); + VecSubf(dir3, origin, co3); + + Normalize(dir1); + Normalize(dir2); + Normalize(dir3); + + VecMulf(dir1, epsilon); + VecMulf(dir2, epsilon); + VecMulf(dir3, epsilon); + + /*offset coordinates slightly along view vectors, to avoid + hitting the faces that own the edge.*/ + VecAddf(co1, co1, dir1); + VecAddf(co2, co2, dir2); + VecAddf(co3, co3, dir3); + + Normalize(dir1); + Normalize(dir2); + Normalize(dir3); + + /*do three samplings: left, middle, right*/ + f = edge_ray_cast(tree, co1, dir1, NULL, e); + if (f && !edge_ray_cast(tree, co2, dir2, NULL, e)) + return 1; + else if (f && !edge_ray_cast(tree, co3, dir3, NULL, e)) + return 1; + else if (!f) + return 1; + + return 0; +} diff --git a/source/blender/editors/mesh/editbmesh_bvh.h b/source/blender/editors/mesh/editbmesh_bvh.h new file mode 100644 index 00000000000..fbbf26b24e0 --- /dev/null +++ b/source/blender/editors/mesh/editbmesh_bvh.h @@ -0,0 +1,15 @@ +struct BMEditMesh; +struct BMFace; +struct BMEdge; +struct BMVert; +struct RegionView3D; + +struct BMBVHTree; +typedef struct BMBVHTree BMBVHTree; + +BMBVHTree *BMBVH_NewBVH(struct BMEditMesh *em); +void BMBVH_FreeBVH(BMBVHTree *tree); + +struct BMFace *BMBVH_RayCast(BMBVHTree *tree, float *co, float *dir, float *hitout); +int BMBVH_EdgeVisible(BMBVHTree *tree, struct BMEdge *e, + struct RegionView3D *r3d, struct Object *obedit); diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 8f9dea00a1b..bb69ab16a45 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -104,10 +104,10 @@ void object_facesel_flush_dm(Object *ob) if(me==NULL || dm==NULL || !CustomData_has_layer( &dm->faceData, CD_ORIGINDEX)) return; - faces = dm->getFaceArray(dm); - totface = dm->getNumFaces(dm); + faces = dm->getTessFaceArray(dm); + totface = dm->getNumTessFaces(dm); - index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX); + index_array = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); mf= faces; diff --git a/source/blender/editors/mesh/editmesh.c b/source/blender/editors/mesh/editmesh.c index b0c51131041..e2bbb63f5c5 100644 --- a/source/blender/editors/mesh/editmesh.c +++ b/source/blender/editors/mesh/editmesh.c @@ -53,6 +53,7 @@ #include "BLI_editVert.h" #include "BLI_dynstr.h" #include "BLI_rand.h" +#include "BLI_mempool.h" #include "BKE_cloth.h" #include "BKE_context.h" @@ -72,6 +73,7 @@ #include "BKE_softbody.h" #include "BKE_texture.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "LBM_fluidsim.h" @@ -92,6 +94,8 @@ /* own include */ #include "mesh_intern.h" +#include "bmesh.h" + /* editmesh.c: - add/alloc/free data @@ -113,22 +117,21 @@ static void error() {} /* ************ ADD / REMOVE / FIND ****************** */ -static void *calloc_em(EditMesh *em, size_t size, size_t nr) -{ - return calloc(size, nr); +static void init_editMesh(EditMesh *em) { + if (!em->vertpool) em->vertpool = BLI_mempool_create(sizeof(EditVert), 1, 512); + if (!em->edgepool) em->edgepool = BLI_mempool_create(sizeof(EditEdge), 1, 512); + if (!em->facepool) em->facepool = BLI_mempool_create(sizeof(EditFace), 1, 512); } -/* used to bypass normal calloc with fast one */ -static void *(*callocvert)(EditMesh *, size_t, size_t) = calloc_em; -static void *(*callocedge)(EditMesh *, size_t, size_t) = calloc_em; -static void *(*callocface)(EditMesh *, size_t, size_t) = calloc_em; - EditVert *addvertlist(EditMesh *em, float *vec, EditVert *example) { EditVert *eve; static int hashnr= 0; + + if (!em->vertpool) init_editMesh(em); + + eve= BLI_mempool_calloc(em->vertpool); - eve= callocvert(em, sizeof(EditVert), 1); BLI_addtail(&em->verts, eve); em->totvert++; @@ -158,8 +161,7 @@ void free_editvert (EditMesh *em, EditVert *eve) EM_remove_selection(em, eve, EDITVERT); CustomData_em_free_block(&em->vdata, &eve->data); - if(eve->fast==0) - free(eve); + BLI_mempool_free(em->vertpool, eve); em->totvert--; } @@ -257,11 +259,12 @@ EditEdge *addedgelist(EditMesh *em, EditVert *v1, EditVert *v2, EditEdge *exampl } /* find in hashlist */ + if (!em->edgepool) init_editMesh(em); eed= findedgelist(em, v1, v2); if(eed==NULL) { - eed= (EditEdge *)callocedge(em, sizeof(EditEdge), 1); + eed= (EditEdge *)BLI_mempool_calloc(em->edgepool); eed->v1= v1; eed->v2= v2; BLI_addtail(&em->edges, eed); @@ -294,9 +297,8 @@ void remedge(EditMesh *em, EditEdge *eed) void free_editedge(EditMesh *em, EditEdge *eed) { EM_remove_selection(em, eed, EDITEDGE); - if(eed->fast==0){ - free(eed); - } + + BLI_mempool_free(em->edgepool, eed); } void free_editface(EditMesh *em, EditFace *efa) @@ -308,8 +310,7 @@ void free_editface(EditMesh *em, EditFace *efa) } CustomData_em_free_block(&em->fdata, &efa->data); - if(efa->fast==0) - free(efa); + BLI_mempool_free(em->facepool, efa); em->totface--; } @@ -385,7 +386,9 @@ EditFace *addfacelist(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, Ed if(v1==v2 || v2==v3 || v1==v3) return NULL; if(e2==0) return NULL; - efa= (EditFace *)callocface(em, sizeof(EditFace), 1); + if (!em->facepool) init_editMesh(em); + efa= (EditFace *)BLI_mempool_calloc(em->facepool); + efa->v1= v1; efa->v2= v2; efa->v3= v3; @@ -468,55 +471,10 @@ int editface_containsEdge(EditFace *efa, EditEdge *eed) /* ************************ stuct EditMesh manipulation ***************************** */ -/* fake callocs for fastmalloc below */ -static void *calloc_fastvert(EditMesh *em, size_t size, size_t nr) -{ - EditVert *eve= em->curvert++; - eve->fast= 1; - return eve; -} -static void *calloc_fastedge(EditMesh *em, size_t size, size_t nr) -{ - EditEdge *eed= em->curedge++; - eed->fast= 1; - return eed; -} -static void *calloc_fastface(EditMesh *em, size_t size, size_t nr) -{ - EditFace *efa= em->curface++; - efa->fast= 1; - return efa; -} - -/* allocate 1 chunk for all vertices, edges, faces. These get tagged to - prevent it from being freed -*/ -static void init_editmesh_fastmalloc(EditMesh *em, int totvert, int totedge, int totface) +void set_editMesh(EditMesh *dst, EditMesh *src) { - if(totvert) em->allverts= MEM_callocN(totvert*sizeof(EditVert), "allverts"); - else em->allverts= NULL; - em->curvert= em->allverts; - - if(totedge==0) totedge= 4*totface; // max possible - - if(totedge) em->alledges= MEM_callocN(totedge*sizeof(EditEdge), "alledges"); - else em->alledges= NULL; - em->curedge= em->alledges; - - if(totface) em->allfaces= MEM_callocN(totface*sizeof(EditFace), "allfaces"); - else em->allfaces= NULL; - em->curface= em->allfaces; - - callocvert= calloc_fastvert; - callocedge= calloc_fastedge; - callocface= calloc_fastface; -} - -static void end_editmesh_fastmalloc(void) -{ - callocvert= calloc_em; - callocedge= calloc_em; - callocface= calloc_em; + free_editMesh(dst); + *dst = *src; } /* do not free editmesh itself here */ @@ -528,7 +486,12 @@ void free_editMesh(EditMesh *em) if(em->edges.first) free_edgelist(em, &em->edges); if(em->faces.first) free_facelist(em, &em->faces); if(em->selected.first) BLI_freelistN(&(em->selected)); - + + if (em->vertpool) BLI_mempool_destroy(em->vertpool); + if (em->edgepool) BLI_mempool_destroy(em->edgepool); + if (em->facepool) BLI_mempool_destroy(em->facepool); + em->vertpool = em->edgepool = em->facepool = NULL; + CustomData_free(&em->vdata, 0); CustomData_free(&em->fdata, 0); @@ -744,7 +707,7 @@ static void edge_drawflags(Mesh *me, EditMesh *em) } /* turns Mesh into editmesh */ -void make_editMesh(Scene *scene, Object *ob) +EditMesh *make_editMesh(Scene *scene, Object *ob) { Mesh *me= ob->data; MFace *mface; @@ -759,13 +722,7 @@ void make_editMesh(Scene *scene, Object *ob) float *co; int tot, a, eekadoodle= 0; - if(me->edit_mesh==NULL) - me->edit_mesh= MEM_callocN(sizeof(EditMesh), "editmesh"); - else - /* because of reload */ - free_editMesh(me->edit_mesh); - - em= me->edit_mesh; + em= MEM_callocN(sizeof(EditMesh), "editmesh"); em->selectmode= scene->toolsettings->selectmode; // warning needs to be synced em->act_face = NULL; @@ -773,18 +730,9 @@ void make_editMesh(Scene *scene, Object *ob) em->totedge= me->totedge; em->totface= me->totface; - if(tot==0) { - return; - } - - /* initialize fastmalloc for editmesh */ - init_editmesh_fastmalloc(em, me->totvert, me->totedge, me->totface); - actkey = ob_get_keyblock(ob); if(actkey) { tot= actkey->totelem; - /* undo-ing in past for previous editmode sessions gives corrupt 'keyindex' values */ - undo_editmode_clear(); } /* make editverts */ @@ -892,8 +840,6 @@ void make_editMesh(Scene *scene, Object *ob) error("This Mesh has old style edgecodes, please put it in the bugtracker!"); MEM_freeN(evlist); - - end_editmesh_fastmalloc(); // resets global function pointers if(me->mselect){ //restore editselections @@ -926,14 +872,13 @@ void make_editMesh(Scene *scene, Object *ob) } /* makes Mesh out of editmesh */ -void load_editMesh(Scene *scene, Object *ob) +void load_editMesh(Scene *scene, Object *ob, EditMesh *em) { Mesh *me= ob->data; MVert *mvert, *oldverts; MEdge *medge; MFace *mface; MSelect *mselect; - EditMesh *em= me->edit_mesh; EditVert *eve; EditFace *efa, *efa_act; EditEdge *eed; @@ -1301,6 +1246,7 @@ static EnumPropertyItem prop_separate_types[] = { /* return 1: success */ static int mesh_separate_selected(Scene *scene, Base *editbase) { +#if 0 EditMesh *em, *emnew; EditVert *eve, *v1; EditEdge *eed, *e1; @@ -1348,8 +1294,8 @@ static int mesh_separate_selected(Scene *scene, Base *editbase) basenew->object->data= menew= add_mesh(me->id.name+2); /* empty */ assign_matarar(basenew->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */ me->id.us--; - make_editMesh(scene, basenew->object); - emnew= menew->edit_mesh; + emnew = make_editMesh(scene, basenew->object); + //emnew= menew->edit_mesh; CustomData_copy(&em->vdata, &emnew->vdata, CD_MASK_EDITMESH, CD_DEFAULT, 0); CustomData_copy(&em->edata, &emnew->edata, CD_MASK_EDITMESH, CD_DEFAULT, 0); CustomData_copy(&em->fdata, &emnew->fdata, CD_MASK_EDITMESH, CD_DEFAULT, 0); @@ -1393,7 +1339,7 @@ static int mesh_separate_selected(Scene *scene, Base *editbase) } /* 5 */ - load_editMesh(scene, basenew->object); + load_editMesh(scene, basenew->object, emnew); free_editMesh(emnew); MEM_freeN(menew->edit_mesh); menew->edit_mesh= NULL; @@ -1407,11 +1353,13 @@ static int mesh_separate_selected(Scene *scene, Base *editbase) BKE_mesh_end_editmesh(me, em); return 1; +#endif } /* return 1: success */ static int mesh_separate_material(Scene *scene, Base *editbase) { +#if 0 Mesh *me= editbase->object->data; EditMesh *em= BKE_mesh_get_editmesh(me); unsigned char curr_mat; @@ -1430,11 +1378,14 @@ static int mesh_separate_material(Scene *scene, Base *editbase) BKE_mesh_end_editmesh(me, em); return 1; +#endif } /* return 1: success */ static int mesh_separate_loose(Scene *scene, Base *editbase) { + return 0; +#if 0 Mesh *me; EditMesh *em; int doit= 1; @@ -1463,6 +1414,7 @@ static int mesh_separate_loose(Scene *scene, Base *editbase) BKE_mesh_end_editmesh(me, em); return 1; +#endif } @@ -1547,6 +1499,7 @@ typedef struct UndoMesh { EditVertC *verts; EditEdgeC *edges; EditFaceC *faces; + EditFaceC *act_face; EditSelectionC *selected; int totvert, totedge, totface, totsel; short selectmode; @@ -1555,247 +1508,6 @@ typedef struct UndoMesh { CustomData vdata, edata, fdata; } UndoMesh; -/* for callbacks */ - -static void free_undoMesh(void *umv) -{ - UndoMesh *um= umv; - - if(um->verts) MEM_freeN(um->verts); - if(um->edges) MEM_freeN(um->edges); - if(um->faces) MEM_freeN(um->faces); - if(um->selected) MEM_freeN(um->selected); -// XXX if(um->retopo_paint_data) retopo_free_paint_data(um->retopo_paint_data); - CustomData_free(&um->vdata, um->totvert); - CustomData_free(&um->edata, um->totedge); - CustomData_free(&um->fdata, um->totface); - MEM_freeN(um); -} - -static void *editMesh_to_undoMesh(void *emv) -{ - EditMesh *em= (EditMesh *)emv; - UndoMesh *um; - EditVert *eve; - EditEdge *eed; - EditFace *efa; - EditSelection *ese; - EditVertC *evec=NULL; - EditEdgeC *eedc=NULL; - EditFaceC *efac=NULL; - EditSelectionC *esec=NULL; - int a; - - um= MEM_callocN(sizeof(UndoMesh), "undomesh"); - - um->selectmode = em->selectmode; - - for(eve=em->verts.first; eve; eve= eve->next) um->totvert++; - for(eed=em->edges.first; eed; eed= eed->next) um->totedge++; - for(efa=em->faces.first; efa; efa= efa->next) um->totface++; - for(ese=em->selected.first; ese; ese=ese->next) um->totsel++; - /* malloc blocks */ - - if(um->totvert) evec= um->verts= MEM_callocN(um->totvert*sizeof(EditVertC), "allvertsC"); - if(um->totedge) eedc= um->edges= MEM_callocN(um->totedge*sizeof(EditEdgeC), "alledgesC"); - if(um->totface) efac= um->faces= MEM_callocN(um->totface*sizeof(EditFaceC), "allfacesC"); - if(um->totsel) esec= um->selected= MEM_callocN(um->totsel*sizeof(EditSelectionC), "allselections"); - - if(um->totvert) CustomData_copy(&em->vdata, &um->vdata, CD_MASK_EDITMESH, CD_CALLOC, um->totvert); - if(um->totedge) CustomData_copy(&em->edata, &um->edata, CD_MASK_EDITMESH, CD_CALLOC, um->totedge); - if(um->totface) CustomData_copy(&em->fdata, &um->fdata, CD_MASK_EDITMESH, CD_CALLOC, um->totface); - - /* now copy vertices */ - a = 0; - for(eve=em->verts.first; eve; eve= eve->next, evec++, a++) { - VECCOPY(evec->co, eve->co); - VECCOPY(evec->no, eve->no); - - evec->f= eve->f; - evec->h= eve->h; - evec->keyindex= eve->keyindex; - eve->tmp.l = a; /*store index*/ - evec->bweight= (short)(eve->bweight*255.0); - - CustomData_from_em_block(&em->vdata, &um->vdata, eve->data, a); - } - - /* copy edges */ - a = 0; - for(eed=em->edges.first; eed; eed= eed->next, eedc++, a++) { - eedc->v1= (int)eed->v1->tmp.l; - eedc->v2= (int)eed->v2->tmp.l; - eedc->f= eed->f; - eedc->h= eed->h; - eedc->seam= eed->seam; - eedc->sharp= eed->sharp; - eedc->crease= (short)(eed->crease*255.0); - eedc->bweight= (short)(eed->bweight*255.0); - eedc->fgoni= eed->fgoni; - eed->tmp.l = a; /*store index*/ - CustomData_from_em_block(&em->edata, &um->edata, eed->data, a); - - } - - /* copy faces */ - a = 0; - for(efa=em->faces.first; efa; efa= efa->next, efac++, a++) { - efac->v1= (int)efa->v1->tmp.l; - efac->v2= (int)efa->v2->tmp.l; - efac->v3= (int)efa->v3->tmp.l; - if(efa->v4) efac->v4= (int)efa->v4->tmp.l; - else efac->v4= -1; - - efac->mat_nr= efa->mat_nr; - efac->flag= efa->flag; - efac->f= efa->f; - efac->h= efa->h; - efac->fgonf= efa->fgonf; - - efa->tmp.l = a; /*store index*/ - - CustomData_from_em_block(&em->fdata, &um->fdata, efa->data, a); - } - - a = 0; - for(ese=em->selected.first; ese; ese=ese->next, esec++){ - esec->type = ese->type; - if(ese->type == EDITVERT) a = esec->index = ((EditVert*)ese->data)->tmp.l; - else if(ese->type == EDITEDGE) a = esec->index = ((EditEdge*)ese->data)->tmp.l; - else if(ese->type == EDITFACE) a = esec->index = ((EditFace*)ese->data)->tmp.l; - } - -// XXX um->retopo_paint_data= retopo_paint_data_copy(em->retopo_paint_data); -// um->retopo_mode= scene->toolsettings->retopo_mode; - - return um; -} - -static void undoMesh_to_editMesh(void *umv, void *emv) -{ - EditMesh *em= (EditMesh *)emv; - UndoMesh *um= (UndoMesh *)umv; - EditVert *eve, **evar=NULL; - EditEdge *eed; - EditFace *efa; - EditSelection *ese; - EditVertC *evec; - EditEdgeC *eedc; - EditFaceC *efac; - EditSelectionC *esec; - int a=0; - - free_editMesh(em); - - /* malloc blocks */ - memset(em, 0, sizeof(EditMesh)); - - em->selectmode = um->selectmode; - - init_editmesh_fastmalloc(em, um->totvert, um->totedge, um->totface); - - CustomData_free(&em->vdata, 0); - CustomData_free(&em->edata, 0); - CustomData_free(&em->fdata, 0); - - CustomData_copy(&um->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0); - CustomData_copy(&um->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0); - CustomData_copy(&um->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0); - - /* now copy vertices */ - - if(um->totvert) evar= MEM_mallocN(um->totvert*sizeof(EditVert *), "vertex ar"); - for(a=0, evec= um->verts; a<um->totvert; a++, evec++) { - eve= addvertlist(em, evec->co, NULL); - evar[a]= eve; - - VECCOPY(eve->no, evec->no); - eve->f= evec->f; - eve->h= evec->h; - eve->keyindex= evec->keyindex; - eve->bweight= ((float)evec->bweight)/255.0f; - - CustomData_to_em_block(&um->vdata, &em->vdata, a, &eve->data); - } - - /* copy edges */ - for(a=0, eedc= um->edges; a<um->totedge; a++, eedc++) { - eed= addedgelist(em, evar[eedc->v1], evar[eedc->v2], NULL); - - eed->f= eedc->f; - eed->h= eedc->h; - eed->seam= eedc->seam; - eed->sharp= eedc->sharp; - eed->fgoni= eedc->fgoni; - eed->crease= ((float)eedc->crease)/255.0f; - eed->bweight= ((float)eedc->bweight)/255.0f; - CustomData_to_em_block(&um->edata, &em->edata, a, &eed->data); - } - - /* copy faces */ - for(a=0, efac= um->faces; a<um->totface; a++, efac++) { - if(efac->v4 != -1) - efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], evar[efac->v4], NULL, NULL); - else - efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], NULL, NULL ,NULL); - - efa->mat_nr= efac->mat_nr; - efa->flag= efac->flag; - efa->f= efac->f; - efa->h= efac->h; - efa->fgonf= efac->fgonf; - - CustomData_to_em_block(&um->fdata, &em->fdata, a, &efa->data); - } - - end_editmesh_fastmalloc(); - if(evar) MEM_freeN(evar); - - em->totvert = um->totvert; - em->totedge = um->totedge; - em->totface = um->totface; - /*restore stored editselections*/ - if(um->totsel){ - EM_init_index_arrays(em, 1,1,1); - for(a=0, esec= um->selected; a<um->totsel; a++, esec++){ - ese = MEM_callocN(sizeof(EditSelection), "Edit Selection"); - ese->type = esec->type; - if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(esec->index); else - if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(esec->index); else - if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(esec->index); - BLI_addtail(&(em->selected),ese); - } - EM_free_index_arrays(); - } - -// XXX retopo_free_paint(); -// em->retopo_paint_data= retopo_paint_data_copy(um->retopo_paint_data); -// scene->toolsettings->retopo_mode= um->retopo_mode; -// if(scene->toolsettings->retopo_mode) { -// XXX if(G.vd->depths) G.vd->depths->damaged= 1; -// retopo_queue_updates(G.vd); -// retopo_paint_view_update(G.vd); -// } - -} - -static void *getEditMesh(bContext *C) -{ - Object *obedit= CTX_data_edit_object(C); - if(obedit && obedit->type==OB_MESH) { - Mesh *me= obedit->data; - return me->edit_mesh; - } - return NULL; -} - -/* and this is all the undo system needs to know */ -void undo_push_mesh(bContext *C, char *name) -{ - undo_editmode_push(C, name, getEditMesh, free_undoMesh, undoMesh_to_editMesh, editMesh_to_undoMesh, NULL); -} - - /* *************** END UNDO *************/ @@ -1898,6 +1610,6 @@ void em_setup_viewcontext(bContext *C, ViewContext *vc) if(vc->obedit) { Mesh *me= vc->obedit->data; - vc->em= me->edit_mesh; + vc->em= me->edit_btmesh; } } diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index d703ba1fb35..e6baa6d9db8 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -60,6 +60,7 @@ #include "BKE_object.h" #include "BKE_utildefines.h" #include "BKE_report.h" +#include "BKE_tessmesh.h" #include "WM_api.h" #include "WM_types.h" @@ -72,6 +73,8 @@ #include "ED_view3d.h" #include "ED_object.h" +#include "bmesh.h" + #include "mesh_intern.h" /* bpymenu removed XXX */ @@ -117,129 +120,6 @@ static short icoface[20][3] = { {10,9,11} }; -/* *************** add-click-mesh (extrude) operator ************** */ - -static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event) -{ - ViewContext vc; - EditVert *eve, *v1; - float min[3], max[3]; - int done= 0; - - em_setup_viewcontext(C, &vc); - - INIT_MINMAX(min, max); - - for(v1= vc.em->verts.first;v1; v1=v1->next) { - if(v1->f & SELECT) { - DO_MINMAX(v1->co, min, max); - done= 1; - } - } - - /* call extrude? */ - if(done) { - EditEdge *eed; - float vec[3], cent[3], mat[3][3]; - float nor[3]= {0.0, 0.0, 0.0}; - - /* check for edges that are half selected, use for rotation */ - done= 0; - for(eed= vc.em->edges.first; eed; eed= eed->next) { - if( (eed->v1->f & SELECT)+(eed->v2->f & SELECT) == SELECT ) { - if(eed->v1->f & SELECT) VecSubf(vec, eed->v1->co, eed->v2->co); - else VecSubf(vec, eed->v2->co, eed->v1->co); - VecAddf(nor, nor, vec); - done= 1; - } - } - if(done) Normalize(nor); - - /* center */ - VecAddf(cent, min, max); - VecMulf(cent, 0.5f); - VECCOPY(min, cent); - - Mat4MulVecfl(vc.obedit->obmat, min); // view space - view3d_get_view_aligned_coordinate(&vc, min, event->mval); - Mat4Invert(vc.obedit->imat, vc.obedit->obmat); - Mat4MulVecfl(vc.obedit->imat, min); // back in object space - - VecSubf(min, min, cent); - - /* calculate rotation */ - Mat3One(mat); - if(done) { - float dot; - - VECCOPY(vec, min); - Normalize(vec); - dot= INPR(vec, nor); - - if( fabs(dot)<0.999) { - float cross[3], si, q1[4]; - - Crossf(cross, nor, vec); - Normalize(cross); - dot= 0.5f*saacos(dot); - si= (float)sin(dot); - q1[0]= (float)cos(dot); - q1[1]= cross[0]*si; - q1[2]= cross[1]*si; - q1[3]= cross[2]*si; - - QuatToMat3(q1, mat); - } - } - - extrudeflag(vc.obedit, vc.em, SELECT, nor); - rotateflag(vc.em, SELECT, cent, mat); - translateflag(vc.em, SELECT, min); - - recalc_editnormals(vc.em); - } - else { - float mat[3][3],imat[3][3]; - float *curs= give_cursor(vc.scene, vc.v3d); - - VECCOPY(min, curs); - view3d_get_view_aligned_coordinate(&vc, min, event->mval); - - eve= addvertlist(vc.em, 0, NULL); - - Mat3CpyMat4(mat, vc.obedit->obmat); - Mat3Inv(imat, mat); - - VECCOPY(eve->co, min); - Mat3MulVecfl(imat, eve->co); - VecSubf(eve->co, eve->co, vc.obedit->obmat[3]); - - eve->f= SELECT; - } - - //retopo_do_all(); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, vc.obedit->data); - DAG_id_flush_update(vc.obedit->data, OB_RECALC_DATA); - - return OPERATOR_FINISHED; -} - -void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Duplicate or Extrude at 3D Cursor"; - ot->description= "Duplicate and extrude selected vertices, edges or faces towards 3D Cursor."; - ot->idname= "MESH_OT_dupli_extrude_cursor"; - - /* api callbacks */ - ot->invoke= dupli_extrude_cursor; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - - /* ********************** */ /* selected faces get hidden edges */ @@ -668,12 +548,53 @@ void addfaces_from_edgenet(EditMesh *em) // XXX DAG_id_flush_update(obedit->data, OB_RECALC_DATA); } -static void addedgeface_mesh(EditMesh *em, wmOperator *op) +static void addedgeface_mesh(Mesh *me, BMEditMesh *bem, wmOperator *op) { + EditMesh *em; EditVert *eve, *neweve[4]; EditEdge *eed; EditFace *efa; short amount=0; + + /*return if bmesh vert connect does anything.*/ + if (bem->selectmode & SCE_SELECT_VERTEX) { + BMesh *bm = bem->bm; + BMOperator bmop; + int len, ok; + + EDBM_InitOpf(bem, &bmop, op, "connectverts verts=%hv", BM_SELECT); + BMO_Exec_Op(bem->bm, &bmop); + + len = BMO_GetSlot(&bmop, "edgeout")->len; + + ok = EDBM_FinishOp(bem, &bmop, op, 1); + if (!ok) return; + + if (len) return; + } + + /*return if bmesh face dissolve finds stuff to + dissolve. this entire tool should be + bmeshafied eventually, but until then + hacks like this to integrate with it + are necassary.*/ + if (bem->selectmode & SCE_SELECT_VERTEX) { + BMesh *bm = bem->bm; + BMOperator bmop; + int len, ok; + + EDBM_InitOpf(bem, &bmop, op, "dissolvefaces faces=%hf", BM_SELECT); + BMO_Exec_Op(bem->bm, &bmop); + + len = BMO_GetSlot(&bmop, "regionout")->len; + + ok = EDBM_FinishOp(bem, &bmop, op, 1); + if (!ok) return; + + if (len) return; + } + + em = BKE_mesh_get_editmesh(me); /* how many selected ? */ if(em->selectmode & SCE_SELECT_EDGE) { @@ -693,16 +614,19 @@ static void addedgeface_mesh(EditMesh *em, wmOperator *op) if(amount==2) { eed= addedgelist(em, neweve[0], neweve[1], NULL); EM_select_edge(eed, 1); - + + BKE_mesh_end_editmesh(me, em); // XXX DAG_id_flush_update(obedit->data, OB_RECALC_DATA); return; } else if(amount > 4) { addfaces_from_edgenet(em); + BKE_mesh_end_editmesh(me, em); return; } else if(amount<2) { BKE_report(op->reports, RPT_ERROR, "More vertices are needed to make an edge/face"); + BKE_mesh_end_editmesh(me, em); return; } @@ -741,6 +665,7 @@ static void addedgeface_mesh(EditMesh *em, wmOperator *op) if(count++ > 4){ addfaces_from_edgenet(em); + BKE_mesh_end_editmesh(me, em); return; } else { /* if 4 edges exist, we just create the face, convex or not */ @@ -782,40 +707,10 @@ static void addedgeface_mesh(EditMesh *em, wmOperator *op) recalc_editnormals(em); } - } -static int addedgeface_mesh_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - - addedgeface_mesh(em, op); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_edge_face_add(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Make Edge/Face"; - ot->description= "Add an edge or face to selected."; - ot->idname= "MESH_OT_edge_face_add"; - - /* api callbacks */ - ot->exec= addedgeface_mesh_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - + BKE_mesh_end_editmesh(me, em); } - - /* ************************ primitives ******************* */ // HACK: these can also be found in cmoview.tga.c, but are here so that they can be found by linker @@ -1106,7 +1001,9 @@ static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int se } dia*=200; - for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0, B_SPHERE,1,0); + + for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0.0, 0, 1, 0); + /* and now do imat */ eve= em->verts.first; while(eve) { @@ -1605,47 +1502,3 @@ void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot) RNA_def_int(ot->srna, "subdivisions", 2, 0, 6, "Subdivisions", "", 0, 8); RNA_def_float(ot->srna, "size", 1.0f, 0.0f, FLT_MAX, "Size", "", 0.001f, 100.00); } - -/****************** add duplicate operator ***************/ - -static int mesh_duplicate_exec(bContext *C, wmOperator *op) -{ - Object *ob= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(ob->data); - - adduplicateflag(em, SELECT); - - BKE_mesh_end_editmesh(ob->data, em); - - DAG_id_flush_update(ob->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); - - return OPERATOR_FINISHED; -} - -static int mesh_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - WM_cursor_wait(1); - mesh_duplicate_exec(C, op); - WM_cursor_wait(0); - - return OPERATOR_FINISHED; -} - -void MESH_OT_duplicate(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Duplicate"; - ot->description= "Duplicate selected vertices, edges or faces."; - ot->idname= "MESH_OT_duplicate"; - - /* api callbacks */ - ot->invoke= mesh_duplicate_invoke; - ot->exec= mesh_duplicate_exec; - - ot->poll= ED_operator_editmesh; - - /* to give to transform */ - RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX); -} - diff --git a/source/blender/editors/mesh/editmesh_lib.c b/source/blender/editors/mesh/editmesh_lib.c index e1b63022dd4..d9e0cc0f339 100644 --- a/source/blender/editors/mesh/editmesh_lib.c +++ b/source/blender/editors/mesh/editmesh_lib.c @@ -61,6 +61,7 @@ editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data #include "ED_view3d.h" #include "mesh_intern.h" +#include "bmesh.h" /* ****************** stats *************** */ @@ -1139,10 +1140,128 @@ short extrudeflag_verts_indiv(EditMesh *em, short flag, float *nor) return 'g'; // g is grab } +short BM_extrude_edgeflag(Object *obedit, BMesh *bm, int eflag, float *nor) +{ + BMIter iter; + BMOIter siter; + BMOperator extop; + BMEdge *edge; + BMFace *f; + void *el; + ModifierData *md; + int flag; + + switch (eflag) { + case SELECT: + flag = BM_SELECT; + break; + default: + flag = BM_SELECT; + break; + } + + for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);f;f=BMIter_Step(&iter)) { + add_normal_aligned(nor, f->no); + } + Normalize(nor); + + BMO_Init_Op(&extop, "extrudefaceregion"); + BMO_HeaderFlag_To_Slot(bm, &extop, "edgefacein", + flag, BM_VERT|BM_EDGE|BM_FACE); + + for (edge=BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); edge; edge=BMIter_Step(&iter)) { + BM_Select_Edge(bm, edge, 0); + } + + for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); f; f=BMIter_Step(&iter)) { + BM_Select_Face(bm, f, 0); + } + + /* If a mirror modifier with clipping is on, we need to adjust some + * of the cases above to handle edges on the line of symmetry. + */ + md = obedit->modifiers.first; + for (; md; md=md->next) { + if (md->type==eModifierType_Mirror) { + MirrorModifierData *mmd = (MirrorModifierData*) md; + + if(mmd->flag & MOD_MIR_CLIPPING) { + float mtx[4][4]; + if (mmd->mirror_ob) { + float imtx[4][4]; + Mat4Invert(imtx, mmd->mirror_ob->obmat); + Mat4MulMat4(mtx, obedit->obmat, imtx); + } + + for (edge=BMIter_New(&iter,bm,BM_EDGES_OF_MESH,NULL); + edge; edge=BMIter_Step(&iter)) + { + if(edge->head.flag & flag) { + float co1[3], co2[3]; + + VecCopyf(co1, edge->v1->co); + VecCopyf(co2, edge->v2->co); + + if (mmd->mirror_ob) { + VecMat4MulVecfl(co1, mtx, co1); + VecMat4MulVecfl(co2, mtx, co2); + } + + if (mmd->flag & MOD_MIR_AXIS_X) + if ( (fabs(co1[0]) < mmd->tolerance) && + (fabs(co2[0]) < mmd->tolerance) ) + BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL); + + if (mmd->flag & MOD_MIR_AXIS_Y) + if ( (fabs(co1[1]) < mmd->tolerance) && + (fabs(co2[1]) < mmd->tolerance) ) + BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL); + + if (mmd->flag & MOD_MIR_AXIS_Z) + if ( (fabs(co1[2]) < mmd->tolerance) && + (fabs(co2[2]) < mmd->tolerance) ) + BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL); + } + } + } + } + } + + + BMO_Exec_Op(bm, &extop); + + el = BMO_IterNew(&siter, bm, &extop, "geomout", BM_ALL); + for (; el; el=BMO_IterStep(&siter)) { + BM_Select(bm, el, 1); + } + + BMO_Finish_Op(bm, &extop); + + if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // grab + return 'n'; // normal constraint + +} + + +static short extrudeflag_edge(Object *obedit, EditMesh *em, short flag, float *nor) { + short ret; + EditMesh *em2; + BMesh *bm = editmesh_to_bmesh(em); + + ret = BM_extrude_edgeflag(obedit, bm, flag, nor); + em2 = bmesh_to_editmesh(bm); + + set_editMesh(em, em2); + MEM_freeN(em2); + + EM_select_flush(em); + + return ret; +} /* this is actually a recode of extrudeflag(), using proper edge/face select */ /* hurms, doesnt use 'flag' yet, but its not called by primitive making stuff anyway */ -static short extrudeflag_edge(Object *obedit, EditMesh *em, short flag, float *nor) +static short extrudeflag_edge_old(Object *obedit, EditMesh *em, short flag, float *nor) { /* all select edges/faces: extrude */ /* old select is cleared, in new ones it is set */ @@ -1686,9 +1805,22 @@ short extrudeflag_vert(Object *obedit, EditMesh *em, short flag, float *nor) /* generic extrude */ short extrudeflag(Object *obedit, EditMesh *em, short flag, float *nor) { - if(em->selectmode & SCE_SELECT_VERTEX) - return extrudeflag_vert(obedit, em, flag, nor); - else + if(em->selectmode & SCE_SELECT_VERTEX) { + EditEdge *eed; + + /*ensure vert flags are consistent for edge selections*/ + for (eed=em->edges.first; eed; eed=eed->next) { + if (eed->f & flag) { + eed->v1->f |= flag; + eed->v2->f |= flag; + } else { + if ((eed->v1->f & flag) && (eed->v2->f & flag)) + eed->f |= flag; + } + } + + return extrudeflag_edge(obedit, em, flag, nor); + } else return extrudeflag_edge(obedit, em, flag, nor); } @@ -1912,6 +2044,9 @@ void recalc_editnormals(EditMesh *em) } for(efa= em->faces.first; efa; efa=efa->next) { + if (efa->e1->fgoni||efa->e2->fgoni||efa->e3->fgoni) continue; + if (efa->e4 && efa->e4->fgoni) continue; + if(efa->v4) { CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, efa->n); CalcCent4f(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); diff --git a/source/blender/editors/mesh/editmesh_loop.c b/source/blender/editors/mesh/editmesh_loop.c index 28103828dd4..03f29edc3fd 100644 --- a/source/blender/editors/mesh/editmesh_loop.c +++ b/source/blender/editors/mesh/editmesh_loop.c @@ -62,6 +62,7 @@ editmesh_loop: tools with own drawing subloops, select, knife, subdiv #include "BKE_object.h" #include "BKE_report.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "PIL_time.h" @@ -78,6 +79,7 @@ editmesh_loop: tools with own drawing subloops, select, knife, subdiv #include "ED_view3d.h" #include "mesh_intern.h" +#include "bmesh.h" /* **** XXX ******** */ static void BIF_undo_push() {} @@ -203,6 +205,7 @@ static void edgering_sel(EditMesh *em, EditEdge *startedge, int select, int prev void CutEdgeloop(Object *obedit, wmOperator *op, EditMesh *em, int numcuts) { +#if 0 ViewContext vc; // XXX EditEdge *nearest=NULL, *eed; float fac; @@ -393,6 +396,7 @@ void CutEdgeloop(Object *obedit, wmOperator *op, EditMesh *em, int numcuts) // DAG_id_flush_update(obedit->data, OB_RECALC_DATA); return; +#endif } @@ -476,7 +480,7 @@ static float seg_intersect(EditEdge *e, CutCurve *c, int len, char mode, struct float m1, b1, m2, b2, x21, x22, y21, y22, xi; float yi, x1min, x1max, y1max, y1min, perc=0; float *scr; - float threshold; + float threshold = 0.0; int i; threshold = 0.000001; /*tolerance for vertex intersection*/ @@ -622,29 +626,187 @@ static float seg_intersect(EditEdge *e, CutCurve *c, int len, char mode, struct } +static float bm_seg_intersect(BMEdge *e, CutCurve *c, int len, char mode, + struct GHash *gh, int *isected) +{ +#define MAXSLOPE 100000 + float x11, y11, x12=0, y12=0, x2max, x2min, y2max; + float y2min, dist, lastdist=0, xdiff2, xdiff1; + float m1, b1, m2, b2, x21, x22, y21, y22, xi; + float yi, x1min, x1max, y1max, y1min, perc=0; + float *scr; + float threshold = 0.0; + int i; + + //threshold = 0.000001; /*tolerance for vertex intersection*/ + // XXX threshold = scene->toolsettings->select_thresh / 100; + + /* Get screen coords of verts */ + scr = BLI_ghash_lookup(gh, e->v1); + x21=scr[0]; + y21=scr[1]; + + scr = BLI_ghash_lookup(gh, e->v2); + x22=scr[0]; + y22=scr[1]; + + xdiff2=(x22-x21); + if (xdiff2) { + m2=(y22-y21)/xdiff2; + b2= ((x22*y21)-(x21*y22))/xdiff2; + } + else { + m2=MAXSLOPE; /* Verticle slope */ + b2=x22; + } + + *isected = 0; + + /*check for *exact* vertex intersection first*/ + if(mode!=KNIFE_MULTICUT){ + for (i=0; i<len; i++){ + if (i>0){ + x11=x12; + y11=y12; + } + else { + x11=c[i].x; + y11=c[i].y; + } + x12=c[i].x; + y12=c[i].y; + + /*test e->v1*/ + if((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)){ + perc = 0; + *isected = 1; + return(perc); + } + /*test e->v2*/ + else if((x11 == x22 && y11 == y22) || (x12 == x22 && y12 == y22)){ + perc = 0; + *isected = 2; + return(perc); + } + } + } + + /*now check for edge interesect (may produce vertex intersection as well)*/ + for (i=0; i<len; i++){ + if (i>0){ + x11=x12; + y11=y12; + } + else { + x11=c[i].x; + y11=c[i].y; + } + x12=c[i].x; + y12=c[i].y; + + /* Perp. Distance from point to line */ + if (m2!=MAXSLOPE) dist=(y12-m2*x12-b2);/* /sqrt(m2*m2+1); Only looking for */ + /* change in sign. Skip extra math */ + else dist=x22-x12; + + if (i==0) lastdist=dist; + + /* if dist changes sign, and intersect point in edge's Bound Box*/ + if ((lastdist*dist)<=0){ + xdiff1=(x12-x11); /* Equation of line between last 2 points */ + if (xdiff1){ + m1=(y12-y11)/xdiff1; + b1= ((x12*y11)-(x11*y12))/xdiff1; + } + else{ + m1=MAXSLOPE; + b1=x12; + } + x2max=MAX2(x21,x22)+0.001; /* prevent missed edges */ + x2min=MIN2(x21,x22)-0.001; /* due to round off error */ + y2max=MAX2(y21,y22)+0.001; + y2min=MIN2(y21,y22)-0.001; + + /* Found an intersect, calc intersect point */ + if (m1==m2){ /* co-incident lines */ + /* cut at 50% of overlap area*/ + x1max=MAX2(x11, x12); + x1min=MIN2(x11, x12); + xi= (MIN2(x2max,x1max)+MAX2(x2min,x1min))/2.0; + + y1max=MAX2(y11, y12); + y1min=MIN2(y11, y12); + yi= (MIN2(y2max,y1max)+MAX2(y2min,y1min))/2.0; + } + else if (m2==MAXSLOPE){ + xi=x22; + yi=m1*x22+b1; + } + else if (m1==MAXSLOPE){ + xi=x12; + yi=m2*x12+b2; + } + else { + xi=(b1-b2)/(m2-m1); + yi=(b1*m2-m1*b2)/(m2-m1); + } + + /* Intersect inside bounding box of edge?*/ + if ((xi>=x2min)&&(xi<=x2max)&&(yi<=y2max)&&(yi>=y2min)){ + /*test for vertex intersect that may be 'close enough'*/ + if(mode!=KNIFE_MULTICUT){ + if(xi <= (x21 + threshold) && xi >= (x21 - threshold)){ + if(yi <= (y21 + threshold) && yi >= (y21 - threshold)){ + *isected = 1; + perc = 0; + break; + } + } + if(xi <= (x22 + threshold) && xi >= (x22 - threshold)){ + if(yi <= (y22 + threshold) && yi >= (y22 - threshold)){ + *isected = 2; + perc = 0; + break; + } + } + } + if ((m2<=1.0)&&(m2>=-1.0)) perc = (xi-x21)/(x22-x21); + else perc=(yi-y21)/(y22-y21); /*lower slope more accurate*/ + //isect=32768.0*(perc+0.0000153); /* Percentage in 1/32768ths */ + + break; + } + } + lastdist=dist; + } + return(perc); +} + #define MAX_CUTS 256 static int knife_cut_exec(bContext *C, wmOperator *op) { Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); + BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh; + BMesh *bm = em->bm; ARegion *ar= CTX_wm_region(C); - EditEdge *eed; - EditVert *eve; + BMVert *bv; + BMIter iter; + BMEdge *be; + BMOperator bmop; CutCurve curve[MAX_CUTS]; struct GHash *gh; float isect=0.0; float *scr, co[4]; - int len=0; + int len=0, isected, flag, i; short numcuts=1, mode= RNA_int_get(op->ptr, "type"); /* edit-object needed for matrix, and ar->regiondata for projections to work */ if (ELEM3(NULL, obedit, ar, ar->regiondata)) return OPERATOR_CANCELLED; - if (EM_nvertices_selected(em) < 2) { + if (bm->totvertsel < 2) { error("No edges are selected to operate on"); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED;; } @@ -658,57 +820,52 @@ static int knife_cut_exec(bContext *C, wmOperator *op) RNA_END; if(len<2) { - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED; } - /*store percentage of edge cut for KNIFE_EXACT here.*/ - for(eed=em->edges.first; eed; eed= eed->next) - eed->tmp.fp = 0.0; - /*the floating point coordinates of verts in screen space will be stored in a hash table according to the vertices pointer*/ gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); - for(eve=em->verts.first; eve; eve=eve->next){ + for(bv=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);bv;bv=BMIter_Step(&iter)){ scr = MEM_mallocN(sizeof(float)*2, "Vertex Screen Coordinates"); - VECCOPY(co, eve->co); + VECCOPY(co, bv->co); co[3]= 1.0; Mat4MulVec4fl(obedit->obmat, co); project_float(ar, co, scr); - BLI_ghash_insert(gh, eve, scr); - eve->f1 = 0; /*store vertex intersection flag here*/ - + BLI_ghash_insert(gh, bv, scr); } - eed= em->edges.first; - while(eed) { - if( eed->v1->f & eed->v2->f & SELECT ){ // NOTE: uses vertex select, subdiv doesnt do edges yet - isect= seg_intersect(eed, curve, len, mode, gh); - if (isect!=0.0f) eed->f2= 1; - else eed->f2=0; - eed->tmp.fp= isect; - //printf("isect=%i\n", isect); - } - else { - eed->f2=0; - eed->f1=0; - } - eed= eed->next; + BMO_Init_Op(&bmop, "esubd"); + + i = 0; + /*store percentage of edge cut for KNIFE_EXACT here.*/ + for (be=BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); be; be=BMIter_Step(&iter)) { + if( BM_Selected(bm, be) ) { + isect= bm_seg_intersect(be, curve, len, mode, gh, &isected); + + if (isect != 0.0f) { + if (mode != KNIFE_MULTICUT && mode != KNIFE_MIDPOINT) { + BMO_Insert_MapFloat(bm, &bmop, + "edgepercents", + be, isect); + + } + BMO_SetFlag(bm, be, 1); + } else BMO_ClearFlag(bm, be, 1); + } else BMO_ClearFlag(bm, be, 1); } - if (mode==KNIFE_MIDPOINT) esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE, 1, SUBDIV_SELECT_ORIG); - else if (mode==KNIFE_MULTICUT) esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE, numcuts, SUBDIV_SELECT_ORIG); - else esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE|B_PERCENTSUBD, 1, SUBDIV_SELECT_ORIG); + BMO_Flag_To_Slot(bm, &bmop, "edges", 1, BM_EDGE); - eed=em->edges.first; - while(eed){ - eed->f2=0; - eed->f1=0; - eed=eed->next; - } + BMO_Set_Int(&bmop, "numcuts", numcuts); + flag = B_KNIFE; + if (mode == KNIFE_MIDPOINT) numcuts = 1; + BMO_Set_Int(&bmop, "flag", flag); + BMO_Set_Float(&bmop, "radius", 0); - BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN); + BMO_Exec_Op(bm, &bmop); + BMO_Finish_Op(bm, &bmop); - BKE_mesh_end_editmesh(obedit->data, em); + BLI_ghash_free(gh, NULL, (GHashValFreeFP)WMEM_freeN); DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); @@ -716,7 +873,6 @@ static int knife_cut_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } - void MESH_OT_knife_cut(wmOperatorType *ot) { PropertyRNA *prop; diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c index 74870778d02..a57d56ec1eb 100644 --- a/source/blender/editors/mesh/editmesh_mods.c +++ b/source/blender/editors/mesh/editmesh_mods.c @@ -78,14 +78,13 @@ editmesh_mods.c, UI level access, no geometry changes #include "WM_api.h" #include "WM_types.h" -#include "UI_resources.h" - #include "RNA_access.h" #include "RNA_define.h" #include "ED_mesh.h" #include "ED_screen.h" #include "ED_view3d.h" +#include "bmesh.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -102,6 +101,7 @@ static int pupmenu() {return 0;} void EM_select_mirrored(Object *obedit, EditMesh *em) { +#if 0 if(em->selectmode & SCE_SELECT_VERTEX) { EditVert *eve, *v1; @@ -115,28 +115,25 @@ void EM_select_mirrored(Object *obedit, EditMesh *em) } } } +#endif } -void EM_automerge(Scene *scene, Object *obedit, int update) +void EM_automerge(int update) { - Mesh *me= obedit ? obedit->data : NULL; /* can be NULL */ - int len; - - if ((scene->toolsettings->automerge) && - (obedit && obedit->type==OB_MESH && (obedit->mode & OB_MODE_EDIT)) && - (me->mr==NULL) - ) { - Mesh *me= (Mesh*)obedit->data; - EditMesh *em= me->edit_mesh; - - len = removedoublesflag(em, 1, 1, scene->toolsettings->doublimit); - if (len) { - em->totvert -= len; /* saves doing a countall */ - if (update) { - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - } - } - } +// XXX int len; + +// if ((scene->automerge) && +// (obedit && obedit->type==OB_MESH) && +// (((Mesh*)obedit->data)->mr==NULL) +// ) { +// len = removedoublesflag(1, 1, scene->toolsettings->doublimit); +// if (len) { +// em->totvert -= len; /* saves doing a countall */ +// if (update) { +// DAG_id_flush_update(obedit->data, OB_RECALC_DATA); +// } +// } +// } } /* ****************************** SELECTION ROUTINES **************** */ @@ -333,38 +330,6 @@ int EM_init_backbuf_circle(ViewContext *vc, short xs, short ys, short rads) } -static void findnearestvert__doClosest(void *userData, EditVert *eve, int x, int y, int index) -{ - struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } *data = userData; - - if (data->pass==0) { - if (index<=data->lastIndex) - return; - } else { - if (index>data->lastIndex) - return; - } - - if (data->dist>3) { - int temp = abs(data->mval[0] - x) + abs(data->mval[1]- y); - if ((eve->f&1) == data->select) { - if (data->strict == 1) - return; - else - temp += 5; - } - - if (temp<data->dist) { - data->dist = temp; - data->closest = eve; - data->closestIndex = index; - } - } -} - - - - static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int index) { EditMesh *em= (EditMesh *)handle; @@ -373,917 +338,8 @@ static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int if(eve && (eve->f & SELECT)) return 0; return 1; } -/** - * findnearestvert - * - * dist (in/out): minimal distance to the nearest and at the end, actual distance - * sel: selection bias - * if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts - * if 0, unselected vertice are given the bias - * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased - */ -EditVert *findnearestvert(ViewContext *vc, int *dist, short sel, short strict) -{ - if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)){ - int distance; - unsigned int index; - EditVert *eve; - - if(strict) index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_wireoffs, 0xFFFFFF, &distance, strict, vc->em, findnearestvert__backbufIndextest); - else index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_wireoffs, 0xFFFFFF, &distance, 0, NULL, NULL); - - eve = BLI_findlink(&vc->em->verts, index-1); - - if(eve && distance < *dist) { - *dist = distance; - return eve; - } else { - return NULL; - } - - } - else { - struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } data; - static int lastSelectedIndex=0; - static EditVert *lastSelected=NULL; - - if (lastSelected && BLI_findlink(&vc->em->verts, lastSelectedIndex)!=lastSelected) { - lastSelectedIndex = 0; - lastSelected = NULL; - } - - data.lastIndex = lastSelectedIndex; - data.mval[0] = vc->mval[0]; - data.mval[1] = vc->mval[1]; - data.select = sel; - data.dist = *dist; - data.strict = strict; - data.closest = NULL; - data.closestIndex = 0; - - data.pass = 0; - - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - - mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1); - - if (data.dist>3) { - data.pass = 1; - mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1); - } - - *dist = data.dist; - lastSelected = data.closest; - lastSelectedIndex = data.closestIndex; - - return data.closest; - } -} - -/* returns labda for closest distance v1 to line-piece v2-v3 */ -static float labda_PdistVL2Dfl( float *v1, float *v2, float *v3) -{ - float rc[2], len; - - rc[0]= v3[0]-v2[0]; - rc[1]= v3[1]-v2[1]; - len= rc[0]*rc[0]+ rc[1]*rc[1]; - if(len==0.0f) - return 0.0f; - - return ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len; -} - -/* note; uses v3d, so needs active 3d window */ -static void findnearestedge__doClosest(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index) -{ - struct { ViewContext vc; float mval[2]; int dist; EditEdge *closest; } *data = userData; - float v1[2], v2[2]; - int distance; - - v1[0] = x0; - v1[1] = y0; - v2[0] = x1; - v2[1] = y1; - - distance= PdistVL2Dfl(data->mval, v1, v2); - - if(eed->f & SELECT) distance+=5; - if(distance < data->dist) { - if(data->vc.rv3d->rflag & RV3D_CLIPPING) { - float labda= labda_PdistVL2Dfl(data->mval, v1, v2); - float vec[3]; - - vec[0]= eed->v1->co[0] + labda*(eed->v2->co[0] - eed->v1->co[0]); - vec[1]= eed->v1->co[1] + labda*(eed->v2->co[1] - eed->v1->co[1]); - vec[2]= eed->v1->co[2] + labda*(eed->v2->co[2] - eed->v1->co[2]); - Mat4MulVecfl(data->vc.obedit->obmat, vec); - - if(view3d_test_clipping(data->vc.rv3d, vec)==0) { - data->dist = distance; - data->closest = eed; - } - } - else { - data->dist = distance; - data->closest = eed; - } - } -} -EditEdge *findnearestedge(ViewContext *vc, int *dist) -{ - - if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) { - int distance; - unsigned int index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_solidoffs, em_wireoffs, &distance,0, NULL, NULL); - EditEdge *eed = BLI_findlink(&vc->em->edges, index-1); - - if (eed && distance<*dist) { - *dist = distance; - return eed; - } else { - return NULL; - } - } - else { - struct { ViewContext vc; float mval[2]; int dist; EditEdge *closest; } data; - - data.vc= *vc; - data.mval[0] = vc->mval[0]; - data.mval[1] = vc->mval[1]; - data.dist = *dist; - data.closest = NULL; - - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, 2); - - *dist = data.dist; - return data.closest; - } -} - -static void findnearestface__getDistance(void *userData, EditFace *efa, int x, int y, int index) -{ - struct { short mval[2]; int dist; EditFace *toFace; } *data = userData; - - if (efa==data->toFace) { - int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y); - - if (temp<data->dist) - data->dist = temp; - } -} -static void findnearestface__doClosest(void *userData, EditFace *efa, int x, int y, int index) -{ - struct { short mval[2], pass; int dist, lastIndex, closestIndex; EditFace *closest; } *data = userData; - - if (data->pass==0) { - if (index<=data->lastIndex) - return; - } else { - if (index>data->lastIndex) - return; - } - - if (data->dist>3) { - int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y); - - if (temp<data->dist) { - data->dist = temp; - data->closest = efa; - data->closestIndex = index; - } - } -} -static EditFace *findnearestface(ViewContext *vc, int *dist) -{ - - if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) { - unsigned int index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]); - EditFace *efa = BLI_findlink(&vc->em->faces, index-1); - - if (efa) { - struct { short mval[2]; int dist; EditFace *toFace; } data; - - data.mval[0] = vc->mval[0]; - data.mval[1] = vc->mval[1]; - data.dist = 0x7FFF; /* largest short */ - data.toFace = efa; - - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenFace(vc, findnearestface__getDistance, &data); - - if(vc->em->selectmode == SCE_SELECT_FACE || data.dist<*dist) { /* only faces, no dist check */ - *dist= data.dist; - return efa; - } - } - - return NULL; - } - else { - struct { short mval[2], pass; int dist, lastIndex, closestIndex; EditFace *closest; } data; - static int lastSelectedIndex=0; - static EditFace *lastSelected=NULL; - - if (lastSelected && BLI_findlink(&vc->em->faces, lastSelectedIndex)!=lastSelected) { - lastSelectedIndex = 0; - lastSelected = NULL; - } - - data.lastIndex = lastSelectedIndex; - data.mval[0] = vc->mval[0]; - data.mval[1] = vc->mval[1]; - data.dist = *dist; - data.closest = NULL; - data.closestIndex = 0; - - data.pass = 0; - - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenFace(vc, findnearestface__doClosest, &data); - - if (data.dist>3) { - data.pass = 1; - mesh_foreachScreenFace(vc, findnearestface__doClosest, &data); - } - - *dist = data.dist; - lastSelected = data.closest; - lastSelectedIndex = data.closestIndex; - - return data.closest; - } -} - -/* best distance based on screen coords. - use em->selectmode to define how to use - selected vertices and edges get disadvantage - return 1 if found one -*/ -static int unified_findnearest(ViewContext *vc, EditVert **eve, EditEdge **eed, EditFace **efa) -{ - EditMesh *em= vc->em; - int dist= 75; - - *eve= NULL; - *eed= NULL; - *efa= NULL; - - /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ - view3d_validate_backbuf(vc); - - if(em->selectmode & SCE_SELECT_VERTEX) - *eve= findnearestvert(vc, &dist, SELECT, 0); - if(em->selectmode & SCE_SELECT_FACE) - *efa= findnearestface(vc, &dist); - - dist-= 20; /* since edges select lines, we give dots advantage of 20 pix */ - if(em->selectmode & SCE_SELECT_EDGE) - *eed= findnearestedge(vc, &dist); - - /* return only one of 3 pointers, for frontbuffer redraws */ - if(*eed) { - *efa= NULL; *eve= NULL; - } - else if(*efa) { - *eve= NULL; - } - - return (*eve || *eed || *efa); -} - - -/* **************** SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */ - -/* selects new faces/edges/verts based on the existing selection */ - -/* VERT GROUP */ - -#define SIMVERT_NORMAL 0 -#define SIMVERT_FACE 1 -#define SIMVERT_VGROUP 2 -#define SIMVERT_TOT 3 - -/* EDGE GROUP */ - -#define SIMEDGE_LENGTH 101 -#define SIMEDGE_DIR 102 -#define SIMEDGE_FACE 103 -#define SIMEDGE_FACE_ANGLE 104 -#define SIMEDGE_CREASE 105 -#define SIMEDGE_SEAM 106 -#define SIMEDGE_SHARP 107 -#define SIMEDGE_TOT 108 - -/* FACE GROUP */ - -#define SIMFACE_MATERIAL 201 -#define SIMFACE_IMAGE 202 -#define SIMFACE_AREA 203 -#define SIMFACE_PERIMETER 204 -#define SIMFACE_NORMAL 205 -#define SIMFACE_COPLANAR 206 -#define SIMFACE_TOT 207 - -static EnumPropertyItem prop_similar_types[] = { - {SIMVERT_NORMAL, "NORMAL", 0, "Normal", ""}, - {SIMVERT_FACE, "FACE", 0, "Amount of Vertices in Face", ""}, - {SIMVERT_VGROUP, "VGROUP", 0, "Vertex Groups", ""}, - {SIMEDGE_LENGTH, "LENGTH", 0, "Length", ""}, - {SIMEDGE_DIR, "DIR", 0, "Direction", ""}, - {SIMEDGE_FACE, "FACE", 0, "Amount of Vertices in Face", ""}, - {SIMEDGE_FACE_ANGLE, "FACE_ANGLE", 0, "Face Angles", ""}, - {SIMEDGE_CREASE, "CREASE", 0, "Crease", ""}, - {SIMEDGE_SEAM, "SEAM", 0, "Seam", ""}, - {SIMEDGE_SHARP, "SHARP", 0, "Sharpness", ""}, - {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""}, - {SIMFACE_IMAGE, "IMAGE", 0, "Image", ""}, - {SIMFACE_AREA, "AREA", 0, "Area", ""}, - {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""}, - {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""}, - {SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""}, - {0, NULL, 0, NULL, NULL} -}; - - -/* this as a way to compare the ares, perim of 2 faces thay will scale to different sizes -*0.5 so smaller faces arnt ALWAYS selected with a thresh of 1.0 */ -#define SCALE_CMP(a,b) ((a+a*thresh >= b) && (a-(a*thresh*0.5) <= b)) - -static int similar_face_select__internal(Scene *scene, EditMesh *em, int mode) -{ - EditFace *efa, *base_efa=NULL; - unsigned int selcount=0; /*count how many new faces we select*/ - - /*deselcount, count how many deselected faces are left, so we can bail out early - also means that if there are no deselected faces, we can avoid a lot of looping */ - unsigned int deselcount=0; - float thresh= scene->toolsettings->select_thresh; - short ok=0; - - for(efa= em->faces.first; efa; efa= efa->next) { - if (!efa->h) { - if (efa->f & SELECT) { - efa->f1=1; - ok=1; - } else { - efa->f1=0; - deselcount++; /* a deselected face we may select later */ - } - } - } - - if (!ok || !deselcount) /* no data selected OR no more data to select */ - return 0; - - if (mode==SIMFACE_AREA) { - for(efa= em->faces.first; efa; efa= efa->next) { - efa->tmp.fp= EM_face_area(efa); - } - } else if (mode==SIMFACE_PERIMETER) { - for(efa= em->faces.first; efa; efa= efa->next) { - efa->tmp.fp= EM_face_perimeter(efa); - } - } - - for(base_efa= em->faces.first; base_efa; base_efa= base_efa->next) { - if (base_efa->f1) { /* This was one of the faces originaly selected */ - if (mode==SIMFACE_MATERIAL) { /* same material */ - for(efa= em->faces.first; efa; efa= efa->next) { - if ( - !(efa->f & SELECT) && - !efa->h && - base_efa->mat_nr == efa->mat_nr - ) { - EM_select_face(efa, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } else if (mode==SIMFACE_IMAGE) { /* same image */ - MTFace *tf, *base_tf; - - base_tf = (MTFace*)CustomData_em_get(&em->fdata, base_efa->data, - CD_MTFACE); - - if(!base_tf) - return selcount; - - for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT) && !efa->h) { - tf = (MTFace*)CustomData_em_get(&em->fdata, efa->data, - CD_MTFACE); - - if(base_tf->tpage == tf->tpage) { - EM_select_face(efa, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } - } else if (mode==SIMFACE_AREA || mode==SIMFACE_PERIMETER) { /* same area OR same perimeter, both use the same temp var */ - for(efa= em->faces.first; efa; efa= efa->next) { - if ( - (!(efa->f & SELECT) && !efa->h) && - SCALE_CMP(base_efa->tmp.fp, efa->tmp.fp) - ) { - EM_select_face(efa, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } else if (mode==SIMFACE_NORMAL) { - float angle; - for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT) && !efa->h) { - angle= RAD2DEG(VecAngle2(base_efa->n, efa->n)); - if (angle/180.0<=thresh) { - EM_select_face(efa, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } - } else if (mode==SIMFACE_COPLANAR) { /* same planer */ - float angle, base_dot, dot; - base_dot= Inpf(base_efa->cent, base_efa->n); - for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT) && !efa->h) { - angle= RAD2DEG(VecAngle2(base_efa->n, efa->n)); - if (angle/180.0<=thresh) { - dot=Inpf(efa->cent, base_efa->n); - if (fabs(base_dot-dot) <= thresh) { - EM_select_face(efa, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } - } - } - } - } /* end base_efa loop */ - return selcount; -} - -static int similar_face_select_exec(bContext *C, wmOperator *op) -{ - Scene *scene= CTX_data_scene(C); - Object *obedit= CTX_data_edit_object(C); - Mesh *me= obedit->data; - EditMesh *em= BKE_mesh_get_editmesh(me); - - int selcount = similar_face_select__internal(scene, em, RNA_int_get(op->ptr, "type")); - - if (selcount) { - /* here was an edge-mode only select flush case, has to be generalized */ - EM_selectmode_flush(em); - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - BKE_mesh_end_editmesh(me, em); - return OPERATOR_FINISHED; - } - - BKE_mesh_end_editmesh(me, em); - return OPERATOR_CANCELLED; -} - -/* ***************************************************** */ - -static int similar_edge_select__internal(ToolSettings *ts, EditMesh *em, int mode) -{ - EditEdge *eed, *base_eed=NULL; - unsigned int selcount=0; /* count how many new edges we select*/ - - /*count how many visible selected edges there are, - so we can return when there are none left */ - unsigned int deselcount=0; - - short ok=0; - float thresh= ts->select_thresh; - - for(eed= em->edges.first; eed; eed= eed->next) { - if (!eed->h) { - if (eed->f & SELECT) { - eed->f1=1; - ok=1; - } else { - eed->f1=0; - deselcount++; - } - /* set all eed->tmp.l to 0 we use it later. - for counting face users*/ - eed->tmp.l=0; - eed->f2=0; /* only for mode SIMEDGE_FACE_ANGLE, edge animations */ - } - } - - if (!ok || !deselcount) /* no data selected OR no more data to select*/ - return 0; - - if (mode==SIMEDGE_LENGTH) { /*store length*/ - for(eed= em->edges.first; eed; eed= eed->next) { - if (!eed->h) /* dont calc data for hidden edges*/ - eed->tmp.fp= VecLenf(eed->v1->co, eed->v2->co); - } - } else if (mode==SIMEDGE_FACE) { /*store face users*/ - EditFace *efa; - /* cound how many faces each edge uses use tmp->l */ - for(efa= em->faces.first; efa; efa= efa->next) { - efa->e1->tmp.l++; - efa->e2->tmp.l++; - efa->e3->tmp.l++; - if (efa->e4) efa->e4->tmp.l++; - } - } else if (mode==SIMEDGE_FACE_ANGLE) { /*store edge angles */ - EditFace *efa; - int j; - /* cound how many faces each edge uses use tmp.l */ - for(efa= em->faces.first; efa; efa= efa->next) { - /* here we use the edges temp data to assign a face - if a face has alredy been assigned (eed->f2==1) - we calculate the angle between the current face and - the edges previously found face. - store the angle in eed->tmp.fp (loosing the face eed->tmp.f) - but tagging eed->f2==2, so we know not to look at it again. - This only works for edges that connect to 2 faces. but its good enough - */ - - /* se we can loop through face edges*/ - j=0; - eed= efa->e1; - while (j<4) { - if (j==1) eed= efa->e2; - else if (j==2) eed= efa->e3; - else if (j==3) { - eed= efa->e4; - if (!eed) - break; - } /* done looping */ - - if (!eed->h) { /* dont calc data for hidden edges*/ - if (eed->f2==2) - break; - else if (eed->f2==0) /* first access, assign the face */ - eed->tmp.f= efa; - else if (eed->f2==1) /* second, we assign the angle*/ - eed->tmp.fp= RAD2DEG(VecAngle2(eed->tmp.f->n, efa->n))/180; - eed->f2++; /* f2==0 no face assigned. f2==1 one face found. f2==2 angle calculated.*/ - } - j++; - } - } - } - - for(base_eed= em->edges.first; base_eed; base_eed= base_eed->next) { - if (base_eed->f1) { - if (mode==SIMEDGE_LENGTH) { /* same length */ - for(eed= em->edges.first; eed; eed= eed->next) { - if ( - !(eed->f & SELECT) && - !eed->h && - SCALE_CMP(base_eed->tmp.fp, eed->tmp.fp) - ) { - EM_select_edge(eed, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } else if (mode==SIMEDGE_DIR) { /* same direction */ - float base_dir[3], dir[3], angle; - VecSubf(base_dir, base_eed->v1->co, base_eed->v2->co); - for(eed= em->edges.first; eed; eed= eed->next) { - if (!(eed->f & SELECT) && !eed->h) { - VecSubf(dir, eed->v1->co, eed->v2->co); - angle= RAD2DEG(VecAngle2(base_dir, dir)); - - if (angle>90) /* use the smallest angle between the edges */ - angle= fabs(angle-180.0f); - - if (angle/90.0<=thresh) { - EM_select_edge(eed, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } - } else if (mode==SIMEDGE_FACE) { /* face users */ - for(eed= em->edges.first; eed; eed= eed->next) { - if ( - !(eed->f & SELECT) && - !eed->h && - base_eed->tmp.l==eed->tmp.l - ) { - EM_select_edge(eed, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } else if (mode==SIMEDGE_FACE_ANGLE && base_eed->f2==2) { /* edge angles, f2==2 means the edge has an angle. */ - for(eed= em->edges.first; eed; eed= eed->next) { - if ( - !(eed->f & SELECT) && - !eed->h && - eed->f2==2 && - (fabs(base_eed->tmp.fp-eed->tmp.fp)<=thresh) - ) { - EM_select_edge(eed, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } else if (mode==SIMEDGE_CREASE) { /* edge crease */ - for(eed= em->edges.first; eed; eed= eed->next) { - if ( - !(eed->f & SELECT) && - !eed->h && - (fabs(base_eed->crease-eed->crease) <= thresh) - ) { - EM_select_edge(eed, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } else if (mode==SIMEDGE_SEAM) { /* edge seam */ - for(eed= em->edges.first; eed; eed= eed->next) { - if ( - !(eed->f & SELECT) && - !eed->h && - (eed->seam == base_eed->seam) - ) { - EM_select_edge(eed, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } else if (mode==SIMEDGE_SHARP) { /* edge sharp */ - for(eed= em->edges.first; eed; eed= eed->next) { - if ( - !(eed->f & SELECT) && - !eed->h && - (eed->sharp == base_eed->sharp) - ) { - EM_select_edge(eed, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } - } - } - return selcount; -} -/* wrap the above function but do selection flushing edge to face */ -static int similar_edge_select_exec(bContext *C, wmOperator *op) -{ - ToolSettings *ts= CTX_data_tool_settings(C); - Object *obedit= CTX_data_edit_object(C); - Mesh *me= obedit->data; - EditMesh *em= BKE_mesh_get_editmesh(me); - - int selcount = similar_edge_select__internal(ts, em, RNA_int_get(op->ptr, "type")); - - if (selcount) { - /* here was an edge-mode only select flush case, has to be generalized */ - EM_selectmode_flush(em); - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - BKE_mesh_end_editmesh(me, em); - return OPERATOR_FINISHED; - } - - BKE_mesh_end_editmesh(me, em); - return OPERATOR_CANCELLED; -} - -/* ********************************* */ - -static int similar_vert_select_exec(bContext *C, wmOperator *op) -{ - ToolSettings *ts= CTX_data_tool_settings(C); - Object *obedit= CTX_data_edit_object(C); - Mesh *me= obedit->data; - EditMesh *em= BKE_mesh_get_editmesh(me); - EditVert *eve, *base_eve=NULL; - unsigned int selcount=0; /* count how many new edges we select*/ - - /*count how many visible selected edges there are, - so we can return when there are none left */ - unsigned int deselcount=0; - int mode= RNA_enum_get(op->ptr, "type"); - - short ok=0; - float thresh= ts->select_thresh; - - for(eve= em->verts.first; eve; eve= eve->next) { - if (!eve->h) { - if (eve->f & SELECT) { - eve->f1=1; - ok=1; - } else { - eve->f1=0; - deselcount++; - } - /* set all eve->tmp.l to 0 we use them later.*/ - eve->tmp.l=0; - } - - } - - if (!ok || !deselcount) { /* no data selected OR no more data to select*/ - BKE_mesh_end_editmesh(me, em); - return 0; - } - - if(mode == SIMVERT_FACE) { - /* store face users */ - EditFace *efa; - - /* count how many faces each edge uses use tmp->l */ - for(efa= em->faces.first; efa; efa= efa->next) { - efa->v1->tmp.l++; - efa->v2->tmp.l++; - efa->v3->tmp.l++; - if (efa->v4) efa->v4->tmp.l++; - } - } - - - for(base_eve= em->verts.first; base_eve; base_eve= base_eve->next) { - if (base_eve->f1) { - - if(mode == SIMVERT_NORMAL) { - float angle; - for(eve= em->verts.first; eve; eve= eve->next) { - if (!(eve->f & SELECT) && !eve->h) { - angle= RAD2DEG(VecAngle2(base_eve->no, eve->no)); - if (angle/180.0<=thresh) { - eve->f |= SELECT; - selcount++; - deselcount--; - if (!deselcount) {/*have we selected all posible faces?, if so return*/ - BKE_mesh_end_editmesh(me, em); - return selcount; - } - } - } - } - } - else if(mode == SIMVERT_FACE) { - for(eve= em->verts.first; eve; eve= eve->next) { - if ( - !(eve->f & SELECT) && - !eve->h && - base_eve->tmp.l==eve->tmp.l - ) { - eve->f |= SELECT; - selcount++; - deselcount--; - if (!deselcount) {/*have we selected all posible faces?, if so return*/ - BKE_mesh_end_editmesh(me, em); - return selcount; - } - } - } - } - else if(mode == SIMVERT_VGROUP) { - MDeformVert *dvert, *base_dvert; - short i, j; /* weight index */ - - base_dvert= CustomData_em_get(&em->vdata, base_eve->data, - CD_MDEFORMVERT); - - if (!base_dvert || base_dvert->totweight == 0) { - BKE_mesh_end_editmesh(me, em); - return selcount; - } - - for(eve= em->verts.first; eve; eve= eve->next) { - dvert= CustomData_em_get(&em->vdata, eve->data, - CD_MDEFORMVERT); - - if (dvert && !(eve->f & SELECT) && !eve->h && dvert->totweight) { - /* do the extra check for selection in the following if, so were not - checking verts that may be alredy selected */ - for (i=0; base_dvert->totweight >i && !(eve->f & SELECT); i++) { - for (j=0; dvert->totweight >j; j++) { - if (base_dvert->dw[i].def_nr==dvert->dw[j].def_nr) { - eve->f |= SELECT; - selcount++; - deselcount--; - if (!deselcount) { /*have we selected all posible faces?, if so return*/ - BKE_mesh_end_editmesh(me, em); - return selcount; - } - break; - } - } - } - } - } - } - } - } /* end basevert loop */ - - if(selcount) { - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - BKE_mesh_end_editmesh(me, em); - return OPERATOR_FINISHED; - } - - BKE_mesh_end_editmesh(me, em); - return OPERATOR_CANCELLED; -} - -static int select_similar_exec(bContext *C, wmOperator *op) -{ - int type= RNA_enum_get(op->ptr, "type"); - - if(type < 100) - return similar_vert_select_exec(C, op); - else if(type < 200) - return similar_edge_select_exec(C, op); - else - return similar_face_select_exec(C, op); -} - -static EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA *ptr, int *free) -{ - Object *obedit= CTX_data_edit_object(C); - EnumPropertyItem *item= NULL; - int a, totitem= 0; - - if(obedit && obedit->type == OB_MESH) { - EditMesh *em= BKE_mesh_get_editmesh(obedit->data); - - if(em->selectmode & SCE_SELECT_VERTEX) { - for(a=SIMVERT_NORMAL; a<=SIMVERT_TOT; a++) - RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a); - } - else if(em->selectmode & SCE_SELECT_EDGE) { - for(a=SIMEDGE_LENGTH; a<=SIMEDGE_TOT; a++) - RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a); - } - else if(em->selectmode & SCE_SELECT_FACE) { - for(a=SIMFACE_MATERIAL; a<=SIMFACE_TOT; a++) - RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a); - } - } - - RNA_enum_item_end(&item, &totitem); - *free= 1; - - return item; -} - -void MESH_OT_select_similar(wmOperatorType *ot) -{ - PropertyRNA *prop; - - /* identifiers */ - ot->name= "Select Similar"; - ot->description= "Select similar vertices, edges or faces by property types."; - ot->idname= "MESH_OT_select_similar"; - - /* api callbacks */ - ot->invoke= WM_menu_invoke; - ot->exec= select_similar_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* properties */ - prop= RNA_def_enum(ot->srna, "type", prop_similar_types, SIMVERT_NORMAL, "Type", ""); - RNA_def_enum_funcs(prop, select_similar_type_itemf); -} - /* ******************************************* */ - int mesh_layers_menu_charlen(CustomData *data, int type) { int i, len = 0; @@ -1710,9 +766,9 @@ void mesh_copy_menu(EditMesh *em, wmOperator *op) } } - /* **************** LOOP SELECTS *************** */ +#if 0 /* selects quads in loop direction of indicated edge */ /* only flush over edges with valence <= 2 */ void faceloop_select(EditMesh *em, EditEdge *startedge, int select) @@ -1782,6 +838,7 @@ void faceloop_select(EditMesh *em, EditEdge *startedge, int select) } } } +#endif /* helper for edgeloop_select, checks for eed->f2 tag in faces */ @@ -1990,583 +1047,7 @@ static int loop_multiselect(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void MESH_OT_loop_multi_select(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Multi Select Loops"; - ot->description= "Select a loop of connected edges by connection type."; - ot->idname= "MESH_OT_loop_multi_select"; - - /* api callbacks */ - ot->exec= loop_multiselect; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* properties */ - RNA_def_boolean(ot->srna, "ring", 0, "Ring", ""); -} - - -/* ***************** MAIN MOUSE SELECTION ************** */ - - -/* ***************** loop select (non modal) ************** */ - -static void mouse_mesh_loop(bContext *C, short mval[2], short extend, short ring) -{ - ViewContext vc; - EditMesh *em; - EditEdge *eed; - int select= 1; - int dist= 50; - - em_setup_viewcontext(C, &vc); - vc.mval[0]= mval[0]; - vc.mval[1]= mval[1]; - em= vc.em; - - /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ - view3d_validate_backbuf(&vc); - - eed= findnearestedge(&vc, &dist); - if(eed) { - if(extend==0) EM_clear_flag_all(em, SELECT); - - if((eed->f & SELECT)==0) select=1; - else if(extend) select=0; - - if(em->selectmode & SCE_SELECT_FACE) { - faceloop_select(em, eed, select); - } - else if(em->selectmode & SCE_SELECT_EDGE) { - if(ring) - edgering_select(em, eed, select); - else - edgeloop_select(em, eed, select); - } - else if(em->selectmode & SCE_SELECT_VERTEX) { - if(ring) - edgering_select(em, eed, select); - else - edgeloop_select(em, eed, select); - } - - EM_selectmode_flush(em); -// if (EM_texFaceCheck()) - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit->data); - } -} - -static int mesh_select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - - view3d_operator_needs_opengl(C); - - mouse_mesh_loop(C, event->mval, RNA_boolean_get(op->ptr, "extend"), - RNA_boolean_get(op->ptr, "ring")); - - /* cannot do tweaks for as long this keymap is after transform map */ - return OPERATOR_FINISHED; -} - -void MESH_OT_loop_select(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Loop Select"; - ot->description= "Select a loop of connected edges."; - ot->idname= "MESH_OT_loop_select"; - - /* api callbacks */ - ot->invoke= mesh_select_loop_invoke; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* properties */ - RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); - RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", ""); -} - -/* ******************* mesh shortest path select, uses prev-selected edge ****************** */ - -/* since you want to create paths with multiple selects, it doesn't have extend option */ -static void mouse_mesh_shortest_path(bContext *C, short mval[2]) -{ - ViewContext vc; - EditMesh *em; - EditEdge *eed; - int dist= 50; - - em_setup_viewcontext(C, &vc); - vc.mval[0]= mval[0]; - vc.mval[1]= mval[1]; - em= vc.em; - - /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ - view3d_validate_backbuf(&vc); - - eed= findnearestedge(&vc, &dist); - if(eed) { - Mesh *me= vc.obedit->data; - int path = 0; - - if (em->selected.last) { - EditSelection *ese = em->selected.last; - - if(ese && ese->type == EDITEDGE) { - EditEdge *eed_act; - eed_act = (EditEdge*)ese->data; - if (eed_act != eed) { - if (edgetag_shortest_path(vc.scene, em, eed_act, eed)) { - EM_remove_selection(em, eed_act, EDITEDGE); - path = 1; - } - } - } - } - if (path==0) { - int act = (edgetag_context_check(vc.scene, eed)==0); - edgetag_context_set(vc.scene, eed, act); /* switch the edge option */ - } - - EM_selectmode_flush(em); - - /* even if this is selected it may not be in the selection list */ - if(edgetag_context_check(vc.scene, eed)==0) - EM_remove_selection(em, eed, EDITEDGE); - else - EM_store_selection(em, eed, EDITEDGE); - - /* force drawmode for mesh */ - switch (vc.scene->toolsettings->edge_mode) { - - case EDGE_MODE_TAG_SEAM: - me->drawflag |= ME_DRAWSEAMS; - break; - case EDGE_MODE_TAG_SHARP: - me->drawflag |= ME_DRAWSHARP; - break; - case EDGE_MODE_TAG_CREASE: - me->drawflag |= ME_DRAWCREASES; - break; - case EDGE_MODE_TAG_BEVEL: - me->drawflag |= ME_DRAWBWEIGHTS; - break; - } - - DAG_id_flush_update(vc.obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit->data); - } -} - - -static int mesh_shortest_path_select_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - - view3d_operator_needs_opengl(C); - - mouse_mesh_shortest_path(C, event->mval); - - return OPERATOR_FINISHED; -} - -void MESH_OT_select_shortest_path(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Shortest Path Select"; - ot->description= "Select shortest path between two selections."; - ot->idname= "MESH_OT_select_shortest_path"; - - /* api callbacks */ - ot->invoke= mesh_shortest_path_select_invoke; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* properties */ - RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); -} - - -/* ************************************************** */ - - -/* here actual select happens */ -/* gets called via generic mouse select operator */ -void mouse_mesh(bContext *C, short mval[2], short extend) -{ - ViewContext vc; - EditVert *eve; - EditEdge *eed; - EditFace *efa; - - /* setup view context for argument to callbacks */ - em_setup_viewcontext(C, &vc); - vc.mval[0]= mval[0]; - vc.mval[1]= mval[1]; - - if(unified_findnearest(&vc, &eve, &eed, &efa)) { - - if(extend==0) EM_clear_flag_all(vc.em, SELECT); - - if(efa) { - /* set the last selected face */ - EM_set_actFace(vc.em, efa); - - if( (efa->f & SELECT)==0 ) { - EM_store_selection(vc.em, efa, EDITFACE); - EM_select_face_fgon(vc.em, efa, 1); - } - else if(extend) { - EM_remove_selection(vc.em, efa, EDITFACE); - EM_select_face_fgon(vc.em, efa, 0); - } - } - else if(eed) { - if((eed->f & SELECT)==0) { - EM_store_selection(vc.em, eed, EDITEDGE); - EM_select_edge(eed, 1); - } - else if(extend) { - EM_remove_selection(vc.em, eed, EDITEDGE); - EM_select_edge(eed, 0); - } - } - else if(eve) { - if((eve->f & SELECT)==0) { - eve->f |= SELECT; - EM_store_selection(vc.em, eve, EDITVERT); - } - else if(extend){ - EM_remove_selection(vc.em, eve, EDITVERT); - eve->f &= ~SELECT; - } - } - - EM_selectmode_flush(vc.em); - -// if (EM_texFaceCheck()) { - - if (efa && efa->mat_nr != vc.obedit->actcol-1) { - vc.obedit->actcol= efa->mat_nr+1; - vc.em->mat_nr= efa->mat_nr; -// BIF_preview_changed(ID_MA); - } - } - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit->data); - -} - -/* *********** select linked ************* */ - -/* for use with selectconnected_delimit_mesh only! */ -#define is_edge_delimit_ok(eed) ((eed->tmp.l == 1) && (eed->seam==0)) -#define is_face_tag(efa) is_edge_delimit_ok(efa->e1) || is_edge_delimit_ok(efa->e2) || is_edge_delimit_ok(efa->e3) || (efa->v4 && is_edge_delimit_ok(efa->e4)) - -#define face_tag(efa)\ -if(efa->v4) efa->tmp.l= efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= efa->e4->tmp.l= 1;\ -else efa->tmp.l= efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= 1; - -/* all - 1) use all faces for extending the selection 2) only use the mouse face -* sel - 1) select 0) deselect -* */ - -/* legacy warning, this function combines too much :) */ -static int select_linked_limited_invoke(ViewContext *vc, short all, short sel) -{ - EditMesh *em= vc->em; - EditFace *efa; - EditEdge *eed; - EditVert *eve; - short done=1, change=0; - - if(em->faces.first==0) return OPERATOR_CANCELLED; - - /* flag all edges+faces as off*/ - for(eed= em->edges.first; eed; eed= eed->next) - eed->tmp.l=0; - - for(efa= em->faces.first; efa; efa= efa->next) { - efa->tmp.l = 0; - } - - if (all) { - // XXX verts? - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f & SELECT) - eed->tmp.l= 1; - } - for(efa= em->faces.first; efa; efa= efa->next) { - - if (efa->f & SELECT) { - face_tag(efa); - } else { - efa->tmp.l = 0; - } - } - } - else { - if( unified_findnearest(vc, &eve, &eed, &efa) ) { - - if(efa) { - efa->tmp.l = 1; - face_tag(efa); - } - else if(eed) - eed->tmp.l= 1; - else { - for(eed= em->edges.first; eed; eed= eed->next) - if(eed->v1==eve || eed->v2==eve) - break; - eed->tmp.l= 1; - } - } - else - return OPERATOR_FINISHED; - } - - while(done==1) { - done= 0; - /* simple algo - select all faces that have a selected edge - * this intern selects the edge, repeat until nothing is left to do */ - for(efa= em->faces.first; efa; efa= efa->next) { - if ((efa->tmp.l == 0) && (!efa->h)) { - if (is_face_tag(efa)) { - face_tag(efa); - done= 1; - } - } - } - } - - for(efa= em->faces.first; efa; efa= efa->next) { - if (efa->tmp.l) { - if (sel) { - if (!(efa->f & SELECT)) { - EM_select_face(efa, 1); - change = 1; - } - } else { - if (efa->f & SELECT) { - EM_select_face(efa, 0); - change = 1; - } - } - } - } - - if (!change) - return OPERATOR_CANCELLED; - - if (!sel) /* make sure de-selecting faces didnt de-select the verts/edges connected to selected faces, this is common with boundries */ - for(efa= em->faces.first; efa; efa= efa->next) - if (efa->f & SELECT) - EM_select_face(efa, 1); - - // if (EM_texFaceCheck()) - - return OPERATOR_FINISHED; -} - -#undef is_edge_delimit_ok -#undef is_face_tag -#undef face_tag - -static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - Object *obedit= CTX_data_edit_object(C); - ViewContext vc; - EditVert *eve, *v1, *v2; - EditEdge *eed; - EditFace *efa; - short done=1, toggle=0; - int sel= !RNA_boolean_get(op->ptr, "deselect"); - int limit= RNA_boolean_get(op->ptr, "limit"); - - /* unified_finednearest needs ogl */ - view3d_operator_needs_opengl(C); - - /* setup view context for argument to callbacks */ - em_setup_viewcontext(C, &vc); - - if(vc.em->edges.first==0) return OPERATOR_CANCELLED; - - vc.mval[0]= event->mval[0]; - vc.mval[1]= event->mval[1]; - - /* return warning! */ - if(limit) { - int retval= select_linked_limited_invoke(&vc, 0, sel); - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - return retval; - } - - if( unified_findnearest(&vc, &eve, &eed, &efa)==0 ) { - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - - return OPERATOR_CANCELLED; - } - - /* clear test flags */ - for(v1= vc.em->verts.first; v1; v1= v1->next) v1->f1= 0; - - /* start vertex/face/edge */ - if(eve) eve->f1= 1; - else if(eed) eed->v1->f1= eed->v2->f1= 1; - else efa->v1->f1= efa->v2->f1= efa->v3->f1= 1; - - /* set flag f1 if affected */ - while(done==1) { - done= 0; - toggle++; - - if(toggle & 1) eed= vc.em->edges.first; - else eed= vc.em->edges.last; - - while(eed) { - v1= eed->v1; - v2= eed->v2; - - if(eed->h==0) { - if(v1->f1 && v2->f1==0) { - v2->f1= 1; - done= 1; - } - else if(v1->f1==0 && v2->f1) { - v1->f1= 1; - done= 1; - } - } - - if(toggle & 1) eed= eed->next; - else eed= eed->prev; - } - } - - /* now use vertex f1 flag to select/deselect */ - for(eed= vc.em->edges.first; eed; eed= eed->next) { - if(eed->v1->f1 && eed->v2->f1) - EM_select_edge(eed, sel); - } - for(efa= vc.em->faces.first; efa; efa= efa->next) { - if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1)) - EM_select_face(efa, sel); - } - /* no flush needed, connected geometry is done */ - -// if (EM_texFaceCheck()) - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - return OPERATOR_FINISHED; -} - -void MESH_OT_select_linked_pick(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Select Linked"; - ot->description= "(un)select all vertices linked to the active mesh."; - ot->idname= "MESH_OT_select_linked_pick"; - - /* api callbacks */ - ot->invoke= select_linked_pick_invoke; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", ""); - RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", ""); -} - - /* ************************* */ - -void selectconnected_mesh_all(EditMesh *em) -{ - EditVert *v1,*v2; - EditEdge *eed; - short done=1, toggle=0; - - if(em->edges.first==0) return; - - while(done==1) { - done= 0; - - toggle++; - if(toggle & 1) eed= em->edges.first; - else eed= em->edges.last; - - while(eed) { - v1= eed->v1; - v2= eed->v2; - if(eed->h==0) { - if(v1->f & SELECT) { - if( (v2->f & SELECT)==0 ) { - v2->f |= SELECT; - done= 1; - } - } - else if(v2->f & SELECT) { - if( (v1->f & SELECT)==0 ) { - v1->f |= SELECT; - done= 1; - } - } - } - if(toggle & 1) eed= eed->next; - else eed= eed->prev; - } - } - - /* now use vertex select flag to select rest */ - EM_select_flush(em); - - // if (EM_texFaceCheck()) -} - -static int select_linked_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(obedit->data); - - if( RNA_boolean_get(op->ptr, "limit") ) { - ViewContext vc; - em_setup_viewcontext(C, &vc); - select_linked_limited_invoke(&vc, 1, 1); - } - else - selectconnected_mesh_all(em); - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_select_linked(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Select Linked All"; - ot->description= "Select all vertices linked to the active mesh."; - ot->idname= "MESH_OT_select_linked"; - - /* api callbacks */ - ot->exec= select_linked_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", ""); -} - - /* ************************* */ /* swap is 0 or 1, if 1 it hides not selected */ @@ -2672,37 +1153,6 @@ void EM_hide_mesh(EditMesh *em, int swap) // DAG_id_flush_update(obedit->data, OB_RECALC_DATA); } -static int hide_mesh_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - - EM_hide_mesh(em, RNA_boolean_get(op->ptr, "unselected")); - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_hide(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Hide Selection"; - ot->description= "Hide (un)selected vertices, edges or faces."; - ot->idname= "MESH_OT_hide"; - - /* api callbacks */ - ot->exec= hide_mesh_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected."); -} - void EM_reveal_mesh(EditMesh *em) { EditVert *eve; @@ -2739,34 +1189,6 @@ void EM_reveal_mesh(EditMesh *em) // DAG_id_flush_update(obedit->data, OB_RECALC_DATA); } -static int reveal_mesh_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - - EM_reveal_mesh(em); - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_reveal(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Reveal Hidden"; - ot->description= "Reveal all hidden vertices, edges and faces."; - ot->idname= "MESH_OT_reveal"; - - /* api callbacks */ - ot->exec= reveal_mesh_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - int select_by_number_vertices_exec(bContext *C, wmOperator *op) { Object *obedit= CTX_data_edit_object(C); @@ -3212,70 +1634,10 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } -void EM_select_swap(EditMesh *em) /* exported for UV */ +static int bmesh_test_exec(bContext *C, wmOperator *op) { - EditVert *eve; - EditEdge *eed; - EditFace *efa; - - if(em->selectmode & SCE_SELECT_VERTEX) { - - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->h==0) { - if(eve->f & SELECT) eve->f &= ~SELECT; - else eve->f|= SELECT; - } - } - } - else if(em->selectmode & SCE_SELECT_EDGE) { - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->h==0) { - EM_select_edge(eed, !(eed->f & SELECT)); - } - } - } - else { - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->h==0) { - EM_select_face(efa, !(efa->f & SELECT)); - } - } - } - - EM_selectmode_flush(em); - -// if (EM_texFaceCheck()) - -} - -static int select_inverse_mesh_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - - EM_select_swap(em); - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_select_inverse(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Select Inverse"; - ot->description= "Select inverse of (un)selected vertices, edges or faces."; - ot->idname= "MESH_OT_select_inverse"; - - /* api callbacks */ - ot->exec= select_inverse_mesh_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + return OPERATOR_CANCELLED; } - /* ******************** (de)select all operator **************** */ void EM_toggle_select_all(EditMesh *em) /* exported for UV */ @@ -3291,36 +1653,18 @@ void EM_select_all(EditMesh *em) EM_set_flag_all(em, SELECT); } -static int toggle_select_all_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - - EM_toggle_select_all(em); - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); - - return OPERATOR_FINISHED; -} - -void MESH_OT_select_all_toggle(wmOperatorType *ot) +void MESH_OT_bmesh_test(wmOperatorType *ot) { /* identifiers */ - ot->name= "Select/Deselect All"; - ot->description= "(de)select all vertices, edges or faces."; - ot->idname= "MESH_OT_select_all_toggle"; + ot->name= "bmesh test op"; + ot->idname= "MESH_OT_bmesh_test"; /* api callbacks */ - ot->exec= toggle_select_all_exec; + ot->exec= bmesh_test_exec; ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } /* ******************** **************** */ - void EM_select_more(EditMesh *em) { EditVert *eve; @@ -3360,36 +1704,6 @@ void EM_select_more(EditMesh *em) } } -static int select_more(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)) ; - - EM_select_more(em); - -// if (EM_texFaceCheck(em)) - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_select_more(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Select More"; - ot->description= "Select more vertices, edges or faces connected to initial selection."; - ot->idname= "MESH_OT_select_more"; - - /* api callbacks */ - ot->exec= select_more; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - void EM_select_less(EditMesh *em) { EditEdge *eed; @@ -3451,35 +1765,6 @@ void EM_select_less(EditMesh *em) } } -static int select_less(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - - EM_select_less(em); - -// if (EM_texFaceCheck(em)) - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_select_less(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Select Less"; - ot->description= "Select less vertices, edges or faces connected to initial selection."; - ot->idname= "MESH_OT_select_less"; - - /* api callbacks */ - ot->exec= select_less; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - static void selectrandom_mesh(EditMesh *em, float perc) /* randomly selects a user-set % of vertices/edges/faces */ { EditVert *eve; @@ -3580,186 +1865,7 @@ void EM_deselect_by_material(EditMesh *em, int index) EM_selectmode_flush(em); } -static void mesh_selection_type(ToolSettings *ts, EditMesh *em, int val) -{ - if(val>0) { - if(val==1) { - em->selectmode= SCE_SELECT_VERTEX; - EM_selectmode_set(em); - } - else if(val==2) { - //if(ctrl) EM_convertsel(em, em->selectmode, SCE_SELECT_EDGE); - em->selectmode= SCE_SELECT_EDGE; - EM_selectmode_set(em); - } - - else{ - //if((ctrl)) EM_convertsel(em, em->selectmode, SCE_SELECT_FACE); - em->selectmode= SCE_SELECT_FACE; - EM_selectmode_set(em); - } - - /* note, em stores selectmode to be able to pass it on everywhere without scene, - this is only until all select modes and toolsettings are settled more */ - ts->selectmode= em->selectmode; -// if (EM_texFaceCheck()) - } -} - -static EnumPropertyItem prop_mesh_edit_types[] = { - {1, "VERT", ICON_VERTEXSEL, "Vertices", ""}, - {2, "EDGE", ICON_EDGESEL, "Edges", ""}, - {3, "FACE", ICON_FACESEL, "Faces", ""}, - {0, NULL, 0, NULL, NULL} -}; - -static int mesh_selection_type_exec(bContext *C, wmOperator *op) -{ - ToolSettings *ts= CTX_data_tool_settings(C); - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - - mesh_selection_type(ts, em, RNA_enum_get(op->ptr,"type")); - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_selection_type(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Selection Mode"; - ot->description= "Set the selection mode type."; - ot->idname= "MESH_OT_selection_type"; - - /* api callbacks */ - ot->invoke= WM_menu_invoke; - ot->exec= mesh_selection_type_exec; - - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_enum(ot->srna, "type", prop_mesh_edit_types, 0, "Type", "Set the mesh selection type"); - -} -/* ************************* SEAMS AND EDGES **************** */ - -static int editmesh_mark_seam(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - Mesh *me= ((Mesh *)obedit->data); - EditEdge *eed; - int clear = RNA_boolean_get(op->ptr, "clear"); - - /* auto-enable seams drawing */ - if(clear==0) { - me->drawflag |= ME_DRAWSEAMS; - } - - if(clear) { - eed= em->edges.first; - while(eed) { - if((eed->h==0) && (eed->f & SELECT)) { - eed->seam = 0; - } - eed= eed->next; - } - } - else { - eed= em->edges.first; - while(eed) { - if((eed->h==0) && (eed->f & SELECT)) { - eed->seam = 1; - } - eed= eed->next; - } - } - - BKE_mesh_end_editmesh(obedit->data, em); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -void MESH_OT_mark_seam(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Mark Seam"; - ot->description= "(un)mark selected edges as a seam."; - ot->idname= "MESH_OT_mark_seam"; - - /* api callbacks */ - ot->exec= editmesh_mark_seam; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - RNA_def_boolean(ot->srna, "clear", 0, "Clear", ""); -} - -static int editmesh_mark_sharp(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - Mesh *me= ((Mesh *)obedit->data); - int clear = RNA_boolean_get(op->ptr, "clear"); - EditEdge *eed; - - /* auto-enable sharp edge drawing */ - if(clear == 0) { - me->drawflag |= ME_DRAWSHARP; - } - - if(!clear) { - eed= em->edges.first; - while(eed) { - if(!eed->h && (eed->f & SELECT)) eed->sharp = 1; - eed = eed->next; - } - } else { - eed= em->edges.first; - while(eed) { - if(!eed->h && (eed->f & SELECT)) eed->sharp = 0; - eed = eed->next; - } - } - - BKE_mesh_end_editmesh(obedit->data, em); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -void MESH_OT_mark_sharp(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Mark Sharp"; - ot->description= "(un)mark selected edges as sharp."; - ot->idname= "MESH_OT_mark_sharp"; - - /* api callbacks */ - ot->exec= editmesh_mark_sharp; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - RNA_def_boolean(ot->srna, "clear", 0, "Clear", ""); -} - /* **************** NORMALS ************** */ - /* XXX value of select is messed up, it means two things */ void righthandfaces(EditMesh *em, int select) /* makes faces righthand turning */ { @@ -3971,45 +2077,7 @@ void righthandfaces(EditMesh *em, int select) /* makes faces righthand turning * waitcursor(0); } - -static int righthandfaces_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - - /* 'standard' behaviour - check if selected, then apply relevant selection */ - - // XXX need other args - righthandfaces(em, RNA_boolean_get(op->ptr, "inside")); - - BKE_mesh_end_editmesh(obedit->data, em); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); //TODO is this needed ? - - return OPERATOR_FINISHED; -} - -void MESH_OT_normals_make_consistent(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Make Normals Consistent"; - ot->description= "Flip all selected vertex and face normals in a consistent direction."; - ot->idname= "MESH_OT_normals_make_consistent"; - - /* api callbacks */ - ot->exec= righthandfaces_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - RNA_def_boolean(ot->srna, "inside", 0, "Inside", ""); -} - /* ********** ALIGN WITH VIEW **************** */ - - static void editmesh_calc_selvert_center(EditMesh *em, float cent_r[3]) { EditVert *eve; @@ -4182,176 +2250,6 @@ void editmesh_align_view_to_selected(Object *obedit, EditMesh *em, wmOperator *o } /* **************** VERTEX DEFORMS *************** */ - -static int smooth_vertex(bContext *C, wmOperator *op) -{ - ToolSettings *ts= CTX_data_tool_settings(C); - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - EditVert *eve, *eve_mir = NULL; - EditEdge *eed; - float *adror, *adr, fac; - float fvec[3]; - int teller=0; - ModifierData *md; - - /* count */ - eve= em->verts.first; - while(eve) { - if(eve->f & SELECT) teller++; - eve= eve->next; - } - if(teller==0) { - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_CANCELLED; - } - - adr=adror= (float *)MEM_callocN(3*sizeof(float *)*teller, "vertsmooth"); - eve= em->verts.first; - while(eve) { - if(eve->f & SELECT) { - eve->tmp.p = (void*)adr; - eve->f1= 0; - eve->f2= 0; - adr+= 3; - } - eve= eve->next; - } - - /* if there is a mirror modifier with clipping, flag the verts that - * are within tolerance of the plane(s) of reflection - */ - for(md=obedit->modifiers.first; md; md=md->next) { - if(md->type==eModifierType_Mirror) { - MirrorModifierData *mmd = (MirrorModifierData*) md; - - if(mmd->flag & MOD_MIR_CLIPPING) { - for (eve= em->verts.first; eve; eve= eve->next) { - if(eve->f & SELECT) { - - switch(mmd->axis){ - case 0: - if (fabs(eve->co[0]) < mmd->tolerance) - eve->f2 |= 1; - break; - case 1: - if (fabs(eve->co[1]) < mmd->tolerance) - eve->f2 |= 2; - break; - case 2: - if (fabs(eve->co[2]) < mmd->tolerance) - eve->f2 |= 4; - break; - } - } - } - } - } - } - - eed= em->edges.first; - while(eed) { - if( (eed->v1->f & SELECT) || (eed->v2->f & SELECT) ) { - fvec[0]= (eed->v1->co[0]+eed->v2->co[0])/2.0; - fvec[1]= (eed->v1->co[1]+eed->v2->co[1])/2.0; - fvec[2]= (eed->v1->co[2]+eed->v2->co[2])/2.0; - - if((eed->v1->f & SELECT) && eed->v1->f1<255) { - eed->v1->f1++; - VecAddf(eed->v1->tmp.p, eed->v1->tmp.p, fvec); - } - if((eed->v2->f & SELECT) && eed->v2->f1<255) { - eed->v2->f1++; - VecAddf(eed->v2->tmp.p, eed->v2->tmp.p, fvec); - } - } - eed= eed->next; - } - - eve= em->verts.first; - while(eve) { - if(eve->f & SELECT) { - if(eve->f1) { - - if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) { - eve_mir= editmesh_get_x_mirror_vert(obedit, em, eve->co); - } - - adr = eve->tmp.p; - fac= 0.5/(float)eve->f1; - - eve->co[0]= 0.5*eve->co[0]+fac*adr[0]; - eve->co[1]= 0.5*eve->co[1]+fac*adr[1]; - eve->co[2]= 0.5*eve->co[2]+fac*adr[2]; - - - /* clip if needed by mirror modifier */ - if (eve->f2) { - if (eve->f2 & 1) { - eve->co[0]= 0.0f; - } - if (eve->f2 & 2) { - eve->co[1]= 0.0f; - } - if (eve->f2 & 4) { - eve->co[2]= 0.0f; - } - } - - if (eve_mir) { - eve_mir->co[0]=-eve->co[0]; - eve_mir->co[1]= eve->co[1]; - eve_mir->co[2]= eve->co[2]; - } - - } - eve->tmp.p= NULL; - } - eve= eve->next; - } - MEM_freeN(adror); - - recalc_editnormals(em); - - BKE_mesh_end_editmesh(obedit->data, em); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -static int smooth_vertex_exec(bContext *C, wmOperator *op) -{ - int repeat = RNA_int_get(op->ptr, "repeat"); - int i; - - if (!repeat) repeat = 1; - - for (i=0; i<repeat; i++) { - smooth_vertex(C, op); - } - - return OPERATOR_FINISHED; -} - -void MESH_OT_vertices_smooth(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Smooth Vertex"; - ot->description= "Flatten angles of selected vertices."; - ot->idname= "MESH_OT_vertices_smooth"; - - /* api callbacks */ - ot->exec= smooth_vertex_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - RNA_def_int(ot->srna, "repeat", 1, 1, 100, "Smooth Iterations", "", 1, INT_MAX); -} - void vertexnoise(Object *obedit, EditMesh *em) { Material *ma; @@ -4508,45 +2406,3 @@ void flipface(EditMesh *em, EditFace *efa) if(efa->v4) CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, efa->n); else CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n); } - - -static int flip_normals(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - EditFace *efa; - - efa= em->faces.first; - while(efa) { - if( efa->f & SELECT ){ - flipface(em, efa); - } - efa= efa->next; - } - - /* update vertex normals too */ - recalc_editnormals(em); - - BKE_mesh_end_editmesh(obedit->data, em); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -void MESH_OT_flip_normals(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Flip Normals"; - ot->description= "Toggle the direction of selected face's vertex and face normals."; - ot->idname= "MESH_OT_flip_normals"; - - /* api callbacks */ - ot->exec= flip_normals; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index d447040e8ea..9c26c812de9 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -75,6 +75,8 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise #include "BKE_utildefines.h" #include "BKE_bmesh.h" #include "BKE_report.h" +#include "BKE_tessmesh.h" + #include "BIF_gl.h" #include "BIF_glutil.h" @@ -91,6 +93,7 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise #include "UI_interface.h" #include "mesh_intern.h" +#include "bmesh.h" /* XXX */ static int extern_qread() {return 0;} @@ -140,7 +143,7 @@ static int vergface(const void *v1, const void *v2) /* *********************************** */ -static void convert_to_triface(EditMesh *em, int direction) +void convert_to_triface(EditMesh *em, int direction) { EditFace *efa, *efan, *next; float fac; @@ -479,44 +482,6 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) / return a; /* amount */ } -static int removedoublesflag_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - /*char msg[100];*/ - - /*XXX this messes up last operator panel - int cnt = removedoublesflag(em,1,0,RNA_float_get(op->ptr, "limit")); - if(cnt) - { - sprintf(msg, "Removed %d vertices", cnt); - BKE_report(op->reports, RPT_INFO, msg); - }*/ - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_remove_doubles(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Remove Doubles"; - ot->description= "Remove duplicate vertices."; - ot->idname= "MESH_OT_remove_doubles"; - - /* api callbacks */ - ot->exec= removedoublesflag_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - RNA_def_float(ot->srna, "limit", 0.0001f, 0.000001f, 50.0f, "Merge Threshold", "Minimum distance between merged verts", 0.00001f, 2.0f); -} - // XXX is this needed? /* called from buttons */ static void xsortvert_flag__doSetX(void *userData, EditVert *eve, int x, int y, int index) @@ -529,6 +494,7 @@ static void xsortvert_flag__doSetX(void *userData, EditVert *eve, int x, int y, /* all verts with (flag & 'flag') are sorted */ void xsortvert_flag(bContext *C, int flag) { +#if 0 //BMESH_TODO ViewContext vc; EditVert *eve; xvertsort *sortblock; @@ -543,9 +509,7 @@ void xsortvert_flag(bContext *C, int flag) if(eve->f & flag) sortblock[i].v1 = eve; - ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); mesh_foreachScreenVert(&vc, xsortvert_flag__doSetX, sortblock, 0); - qsort(sortblock, amount, sizeof(xvertsort), vergxco); /* make temporal listbase */ @@ -562,7 +526,7 @@ void xsortvert_flag(bContext *C, int flag) addlisttolist(&vc.em->verts, &tbase); MEM_freeN(sortblock); - +#endif } /* called from buttons */ @@ -645,12 +609,15 @@ void extrude_mesh(Scene *scene, Object *obedit, EditMesh *em, wmOperator *op) } else if(em->selectmode & SCE_SELECT_EDGE) { if (em->totedgesel==0) nr = 0; - else if (em->totedgesel==1) nr = 3; + + nr = 1; + /*else if (em->totedgesel==1) nr = 3; else if(em->totfacesel==0) nr = 3; else if(em->totfacesel==1) nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3"); else nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3"); + */ } else { if (em->totfacesel == 0) nr = 0; @@ -700,6 +667,8 @@ void extrude_mesh(Scene *scene, Object *obedit, EditMesh *em, wmOperator *op) } +#if 0 +//need to see if this really had new stuff I should merge over // XXX should be a menu item static int mesh_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event) { @@ -749,7 +718,6 @@ void MESH_OT_extrude(wmOperatorType *ot) { /* identifiers */ ot->name= "Extrude"; - ot->description= "Extrude selected vertices, edges or faces."; ot->idname= "MESH_OT_extrude"; /* api callbacks */ @@ -759,7 +727,13 @@ void MESH_OT_extrude(wmOperatorType *ot) /* 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", ""); } +#endif static int split_mesh(bContext *C, wmOperator *op) { @@ -787,7 +761,6 @@ void MESH_OT_split(wmOperatorType *ot) { /* identifiers */ ot->name= "Split"; - ot->description= "Split selected geometry into separate disconnected mesh."; ot->idname= "MESH_OT_split"; /* api callbacks */ @@ -798,7 +771,9 @@ void MESH_OT_split(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } - +#if 0 +//this also showed up in a merge, need to check if it +//needs changes ported over to new extrude code too static int extrude_repeat_mesh(bContext *C, wmOperator *op) { Object *obedit= CTX_data_edit_object(C); @@ -847,7 +822,6 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot) { /* identifiers */ ot->name= "Extrude Repeat Mesh"; - ot->description= "Extrude selected vertices, edges or faces repeatedly."; ot->idname= "MESH_OT_extrude_repeat"; /* api callbacks */ @@ -861,7 +835,7 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot) RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, 100.0f, "Offset", "", 0.0f, FLT_MAX); RNA_def_int(ot->srna, "steps", 10, 0, 180, "Steps", "", 0, INT_MAX); } - +#endif /* ************************** spin operator ******************** */ @@ -981,7 +955,6 @@ void MESH_OT_spin(wmOperatorType *ot) { /* identifiers */ ot->name= "Spin"; - ot->description= "Extrude selected vertices in a circle around the cursor in indicated viewport."; ot->idname= "MESH_OT_spin"; /* api callbacks */ @@ -1089,7 +1062,6 @@ void MESH_OT_screw(wmOperatorType *ot) { /* identifiers */ ot->name= "Screw"; - ot->description= "Extrude selected vertices in screw-shaped rotation around the cursor in indicated viewport."; ot->idname= "MESH_OT_screw"; /* api callbacks */ @@ -1154,194 +1126,6 @@ static void erase_vertices(EditMesh *em, ListBase *l) } } -void delete_mesh(Object *obedit, EditMesh *em, wmOperator *op, int event) -{ - EditFace *efa, *nextvl; - EditVert *eve,*nextve; - EditEdge *eed,*nexted; - int count; - char *str="Erase"; - - - if(event<1) return; - - if(event==10 ) { - str= "Erase Vertices"; - erase_edges(em, &em->edges); - erase_faces(em, &em->faces); - erase_vertices(em, &em->verts); - } - else if(event==6) { - if(!EdgeLoopDelete(em, op)) - return; - - str= "Erase Edge Loop"; - } - else if(event==4) { - str= "Erase Edges & Faces"; - efa= em->faces.first; - while(efa) { - nextvl= efa->next; - /* delete only faces with 1 or more edges selected */ - count= 0; - if(efa->e1->f & SELECT) count++; - if(efa->e2->f & SELECT) count++; - if(efa->e3->f & SELECT) count++; - if(efa->e4 && (efa->e4->f & SELECT)) count++; - if(count) { - BLI_remlink(&em->faces, efa); - free_editface(em, efa); - } - efa= nextvl; - } - eed= em->edges.first; - while(eed) { - nexted= eed->next; - if(eed->f & SELECT) { - remedge(em, eed); - free_editedge(em, eed); - } - eed= nexted; - } - efa= em->faces.first; - while(efa) { - nextvl= efa->next; - event=0; - if( efa->v1->f & SELECT) event++; - if( efa->v2->f & SELECT) event++; - if( efa->v3->f & SELECT) event++; - if(efa->v4 && (efa->v4->f & SELECT)) event++; - - if(event>1) { - BLI_remlink(&em->faces, efa); - free_editface(em, efa); - } - efa= nextvl; - } - } - else if(event==1) { - str= "Erase Edges"; - // faces first - efa= em->faces.first; - while(efa) { - nextvl= efa->next; - event=0; - if( efa->e1->f & SELECT) event++; - if( efa->e2->f & SELECT) event++; - if( efa->e3->f & SELECT) event++; - if(efa->e4 && (efa->e4->f & SELECT)) event++; - - if(event) { - BLI_remlink(&em->faces, efa); - free_editface(em, efa); - } - efa= nextvl; - } - eed= em->edges.first; - while(eed) { - nexted= eed->next; - if(eed->f & SELECT) { - remedge(em, eed); - free_editedge(em, eed); - } - eed= nexted; - } - /* to remove loose vertices: */ - eed= em->edges.first; - while(eed) { - if( eed->v1->f & SELECT) eed->v1->f-=SELECT; - if( eed->v2->f & SELECT) eed->v2->f-=SELECT; - eed= eed->next; - } - eve= em->verts.first; - while(eve) { - nextve= eve->next; - if(eve->f & SELECT) { - BLI_remlink(&em->verts,eve); - free_editvert(em, eve); - } - eve= nextve; - } - - } - else if(event==2) { - str="Erase Faces"; - delfaceflag(em, SELECT); - } - else if(event==3) { - str= "Erase All"; - if(em->verts.first) free_vertlist(em, &em->verts); - if(em->edges.first) free_edgelist(em, &em->edges); - if(em->faces.first) free_facelist(em, &em->faces); - if(em->selected.first) BLI_freelistN(&(em->selected)); - } - else if(event==5) { - str= "Erase Only Faces"; - efa= em->faces.first; - while(efa) { - nextvl= efa->next; - if(efa->f & SELECT) { - BLI_remlink(&em->faces, efa); - free_editface(em, efa); - } - efa= nextvl; - } - } - - EM_fgon_flags(em); // redo flags and indices for fgons -} - -/* Note, these values must match delete_mesh() event values */ -static EnumPropertyItem prop_mesh_delete_types[] = { - {10,"VERT", 0, "Vertices", ""}, - {1, "EDGE", 0, "Edges", ""}, - {2, "FACE", 0, "Faces", ""}, - {3, "ALL", 0, "All", ""}, - {4, "EDGE_FACE",0, "Edges & Faces", ""}, - {5, "ONLY_FACE",0, "Only Faces", ""}, - {6, "EDGE_LOOP",0, "Edge Loop", ""}, - {0, NULL, 0, NULL, NULL} -}; - -static int delete_mesh_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - int type= RNA_enum_get(op->ptr, "type"); - - if(type==6) - return WM_operator_name_call(C, "MESH_OT_delete_edgeloop", WM_OP_EXEC_DEFAULT, NULL); - - delete_mesh(obedit, em, op, type); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_delete(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Delete"; - ot->description= "Delete selected vertices, edges or faces."; - ot->idname= "MESH_OT_delete"; - - /* api callbacks */ - ot->invoke= WM_menu_invoke; - ot->exec= delete_mesh_exec; - - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /*props */ - RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, 10, "Type", "Method used for deleting mesh data"); -} - - /*GB*/ /*-------------------------------------------------------------------------------*/ /*--------------------------- Edge Based Subdivide ------------------------------*/ @@ -1394,7 +1178,7 @@ static void alter_co(float *co, EditEdge *edge, float smooth, float fractal, int co[1] += vec1[1]; co[2] += vec1[2]; } - else if(beauty & B_SPHERE) { /* subdivide sphere */ + /*else if(beauty & B_SPHERE) { // subdivide sphere Normalize(co); co[0]*= smooth; co[1]*= smooth; @@ -1407,7 +1191,7 @@ static void alter_co(float *co, EditEdge *edge, float smooth, float fractal, int vec1[1]= fac*(float)(0.5-BLI_drand()); vec1[2]= fac*(float)(0.5-BLI_drand()); VecAddf(co, co, vec1); - } + }*/ } /* assumes in the edge is the correct interpolated vertices already */ @@ -2255,7 +2039,7 @@ static void fill_quad_quadruple(EditMesh *em, EditFace *efa, struct GHash *gh, i for(i=1;i<=numcuts;i++) { /* we create a fake edge for the next loop */ - temp.v2 = innerverts[i][0] = verts[1][i]; + temp.v2 = innerverts[i][0] = verts[1][i]; temp.v1 = innerverts[i][numcuts+1] = verts[3][i]; for(j=1;j<=numcuts;j++) { @@ -2394,7 +2178,7 @@ static void fill_tri_triple(EditMesh *em, EditFace *efa, struct GHash *gh, int n MEM_freeN(innerverts); } -//Next two fill types are for knife exact only and are provided to allow for knifing through vertices +//Next two fill types are for exact only and are provided to allow for knifing through vertices //This means there is no multicut! static void fill_quad_doublevert(EditMesh *em, EditFace *efa, int v1, int v2) { @@ -3126,13 +2910,13 @@ static float measure_facepair(EditVert *v1, EditVert *v2, EditVert *v3, EditVert CalcNormFloat(v1->co, v3->co, v4->co, noA2); if(noA1[0] == noA2[0] && noA1[1] == noA2[1] && noA1[2] == noA2[2]) normalADiff = 0.0; - else normalADiff = RAD2DEG(VecAngle2(noA1, noA2)); + else normalADiff = VecAngle2(noA1, noA2); //if(!normalADiff) normalADiff = 179; CalcNormFloat(v2->co, v3->co, v4->co, noB1); CalcNormFloat(v4->co, v1->co, v2->co, noB2); if(noB1[0] == noB2[0] && noB1[1] == noB2[1] && noB1[2] == noB2[2]) normalBDiff = 0.0; - else normalBDiff = RAD2DEG(VecAngle2(noB1, noB2)); + else normalBDiff = VecAngle2(noB1, noB2); //if(!normalBDiff) normalBDiff = 179; measure += (normalADiff/360) + (normalBDiff/360); @@ -3147,10 +2931,10 @@ static float measure_facepair(EditVert *v1, EditVert *v2, EditVert *v3, EditVert diff = 0.0; diff = ( - fabs(RAD2DEG(VecAngle2(edgeVec1, edgeVec2)) - 90) + - fabs(RAD2DEG(VecAngle2(edgeVec2, edgeVec3)) - 90) + - fabs(RAD2DEG(VecAngle2(edgeVec3, edgeVec4)) - 90) + - fabs(RAD2DEG(VecAngle2(edgeVec4, edgeVec1)) - 90)) / 360; + fabs(VecAngle2(edgeVec1, edgeVec2) - 90) + + fabs(VecAngle2(edgeVec2, edgeVec3) - 90) + + fabs(VecAngle2(edgeVec3, edgeVec4) - 90) + + fabs(VecAngle2(edgeVec4, edgeVec1) - 90)) / 360; if(!diff) return 0.0; measure += diff; @@ -3502,13 +3286,6 @@ void edge_flip(EditMesh *em) MEM_freeN(efaar); } -#define DIRECTION_CW 1 -#define DIRECTION_CCW 2 - -static const EnumPropertyItem direction_items[]= { - {DIRECTION_CW, "CW", 0, "Clockwise", ""}, - {DIRECTION_CCW, "CCW", 0, "Counter Clockwise", ""}, - {0, NULL, 0, NULL, NULL}}; #define AXIS_X 1 #define AXIS_Y 2 @@ -3516,273 +3293,8 @@ static const EnumPropertyItem direction_items[]= { static const EnumPropertyItem axis_items[]= { {AXIS_X, "X", 0, "X", ""}, {AXIS_Y, "Y", 0, "Y", ""}, - {0, NULL, 0, NULL, NULL}}; - -static void edge_rotate(EditMesh *em, wmOperator *op, EditEdge *eed, int dir) -{ - EditVert **verts[2]; - EditFace *face[2], *efa, *newFace[2]; - EditEdge **edges[2], **hiddenedges, *srchedge; - int facecount, p1, p2, p3, p4, fac1, fac2, i, j; - int numhidden, numshared, p[2][4]; - - /* check to make sure that the edge is only part of 2 faces */ - facecount = 0; - for(efa = em->faces.first;efa;efa = efa->next) { - if((efa->e1 == eed || efa->e2 == eed) || (efa->e3 == eed || efa->e4 == eed)) { - if(facecount >= 2) { - /* more than two faces with this edge */ - return; - } - else { - face[facecount] = efa; - facecount++; - } - } - } - - if(facecount < 2) - return; - - /* how many edges does each face have */ - if(face[0]->e4) fac1= 4; - else fac1= 3; - - if(face[1]->e4) fac2= 4; - else fac2= 3; - - /* make a handy array for verts and edges */ - verts[0]= &face[0]->v1; - edges[0]= &face[0]->e1; - verts[1]= &face[1]->v1; - edges[1]= &face[1]->e1; - - /* we don't want to rotate edges between faces that share more than one edge */ - numshared= 0; - for(i=0; i<fac1; i++) - for(j=0; j<fac2; j++) - if (edges[0][i] == edges[1][j]) - numshared++; - - if(numshared > 1) - return; - - /* we want to construct an array of vertex indicis in both faces, starting at - the last vertex of the edge being rotated. - - first we find the two vertices that lie on the rotating edge - - then we make sure they are ordered according to the face vertex order - - and then we construct the array */ - p1= p2= p3= p4= 0; - - for(i=0; i<4; i++) { - if(eed->v1 == verts[0][i]) p1 = i; - if(eed->v2 == verts[0][i]) p2 = i; - if(eed->v1 == verts[1][i]) p3 = i; - if(eed->v2 == verts[1][i]) p4 = i; - } - - if((p1+1)%fac1 == p2) - SWAP(int, p1, p2); - if((p3+1)%fac2 == p4) - SWAP(int, p3, p4); - - for (i = 0; i < 4; i++) { - p[0][i]= (p1 + i)%fac1; - p[1][i]= (p3 + i)%fac2; - } - - /* create an Array of the Edges who have h set prior to rotate */ - numhidden = 0; - for(srchedge = em->edges.first;srchedge;srchedge = srchedge->next) - if(srchedge->h && ((srchedge->v1->f & SELECT) || (srchedge->v2->f & SELECT))) - numhidden++; - - hiddenedges = MEM_mallocN(sizeof(EditVert*)*numhidden+1, "RotateEdgeHiddenVerts"); - if(!hiddenedges) { - BKE_report(op->reports, RPT_ERROR, "Memory allocation failed"); - return; - } - - numhidden = 0; - for(srchedge=em->edges.first; srchedge; srchedge=srchedge->next) - if(srchedge->h && (srchedge->v1->f & SELECT || srchedge->v2->f & SELECT)) - hiddenedges[numhidden++] = srchedge; - - /* create the 2 new faces */ - if(fac1 == 3 && fac2 == 3) { - /* no need of reverse setup */ - - newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1); - newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1); - } - else if(fac1 == 4 && fac2 == 3) { - if(dir == DIRECTION_CW) { - newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]); - newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1); - } else if (dir == DIRECTION_CCW) { - newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][2], 4+p[1][1], p[0][0], p[0][1]); - newFace[1]= EM_face_from_faces(em, face[1], face[0], 4+p[0][2], p[1][0], p[1][1], -1); - - verts[0][p[0][2]]->f |= SELECT; - verts[1][p[1][1]]->f |= SELECT; - } - } - else if(fac1 == 3 && fac2 == 4) { - if(dir == DIRECTION_CW) { - newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1); - newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]); - } else if (dir == DIRECTION_CCW) { - newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][0], p[0][1], 4+p[1][2], -1); - newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], 4+p[0][1], 4+p[0][2]); - - verts[0][p[0][1]]->f |= SELECT; - verts[1][p[1][2]]->f |= SELECT; - } - - } - else if(fac1 == 4 && fac2 == 4) { - if(dir == DIRECTION_CW) { - newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]); - newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]); - } else if (dir == DIRECTION_CCW) { - newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][2], p[0][3], 4+p[1][1], 4+p[1][2]); - newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][2], p[1][3], 4+p[0][1], 4+p[0][2]); - - verts[0][p[0][2]]->f |= SELECT; - verts[1][p[1][2]]->f |= SELECT; - } - } - else - return; /* This should never happen */ - - if(dir == DIRECTION_CW || (fac1 == 3 && fac2 == 3)) { - verts[0][p[0][1]]->f |= SELECT; - verts[1][p[1][1]]->f |= SELECT; - } - - /* copy old edge's flags to new center edge*/ - for(srchedge=em->edges.first;srchedge;srchedge=srchedge->next) { - if((srchedge->v1->f & SELECT) && (srchedge->v2->f & SELECT)) { - srchedge->f = eed->f; - srchedge->h = eed->h; - srchedge->dir = eed->dir; - srchedge->seam = eed->seam; - srchedge->crease = eed->crease; - srchedge->bweight = eed->bweight; - } - } - - /* resetting hidden flag */ - for(numhidden--; numhidden>=0; numhidden--) - hiddenedges[numhidden]->h= 1; - - /* check for orhphan edges */ - for(srchedge=em->edges.first; srchedge; srchedge=srchedge->next) - srchedge->f1= -1; - - /* cleanup */ - MEM_freeN(hiddenedges); - - /* get rid of the old edge and faces*/ - remedge(em, eed); - free_editedge(em, eed); - BLI_remlink(&em->faces, face[0]); - free_editface(em, face[0]); - BLI_remlink(&em->faces, face[1]); - free_editface(em, face[1]); -} - -// XXX ton please check -/* only accepts 1 selected edge, or 2 selected faces */ -static int edge_rotate_selected(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - EditEdge *eed; - EditFace *efa; - int dir = RNA_int_get(op->ptr, "direction"); // dir == 2 when clockwise and ==1 for counter CW. - short edgeCount = 0; - - /*clear new flag for new edges, count selected edges */ - for(eed= em->edges.first; eed; eed= eed->next) { - eed->f1= 0; - eed->f2 &= ~2; - if(eed->f & SELECT) edgeCount++; - } - - if(edgeCount>1) { - /* more selected edges, check faces */ - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - efa->e1->f1++; - efa->e2->f1++; - efa->e3->f1++; - if(efa->e4) efa->e4->f1++; - } - } - edgeCount= 0; - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f1==2) edgeCount++; - } - if(edgeCount==1) { - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f1==2) { - edge_rotate(em, op, eed,dir); - break; - } - } - } - else - { - BKE_report(op->reports, RPT_ERROR, "Select one edge or two adjacent faces"); - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_CANCELLED; - } - } - else if(edgeCount==1) { - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f & SELECT) { - EM_select_edge(eed, 0); - edge_rotate(em, op, eed,dir); - break; - } - } - } - else { - BKE_report(op->reports, RPT_ERROR, "Select one edge or two adjacent faces"); - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_CANCELLED; - } - - /* flush selected vertices (again) to edges/faces */ - EM_select_flush(em); - - BKE_mesh_end_editmesh(obedit->data, em); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -void MESH_OT_edge_rotate(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Rotate Selected Edge"; - ot->description= "Rotate selected edge or adjoining faces."; - ot->idname= "MESH_OT_edge_rotate"; - - /* api callbacks */ - ot->exec= edge_rotate_selected; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "direction", "direction to rotate edge around."); -} - + {0, NULL, 0, NULL, NULL}, +}; /******************* BEVEL CODE STARTS HERE ********************/ @@ -3873,11 +3385,11 @@ typedef struct SlideVert { EditVert origvert; } SlideVert; -#if 0 int EdgeSlide(EditMesh *em, wmOperator *op, short immediate, float imperc) { return 0; /* XXX REFACTOR - #if 0'd for now, otherwise can't make 64bit windows builds on 64bit machine */ +#if 0 useless: goto useless // because it doesn't do anything right now @@ -4659,35 +4171,9 @@ useless: } return 1; -} #endif // END OF XXX - -int EdgeLoopDelete(EditMesh *em, wmOperator *op) -{ -#if 0 //XXX won't work with new edgeslide - - /* temporal flag setting so we keep UVs when deleting edge loops, - * this is a bit of a hack but it works how you would want in almost all cases */ - // short uvcalc_flag_orig = 0; // XXX scene->toolsettings->uvcalc_flag; - // scene->toolsettings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT; - - if(!EdgeSlide(em, op, 1, 1)) { - return 0; - } - - /* restore uvcalc flag */ - // scene->toolsettings->uvcalc_flag = uvcalc_flag_orig; - - EM_select_more(em); - removedoublesflag(em, 1,0, 0.001); - EM_select_flush(em); - // DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - return 1; -#endif - return 0; } - /* -------------------- More tools ------------------ */ #if 0 void mesh_set_face_flags(EditMesh *em, short mode) @@ -4757,271 +4243,6 @@ void mesh_set_face_flags(EditMesh *em, short mode) } #endif -/********************** Rip Operator *************************/ - -/* helper to find edge for edge_rip */ -static float mesh_rip_edgedist(ARegion *ar, float mat[][4], float *co1, float *co2, short *mval) -{ - float vec1[3], vec2[3], mvalf[2]; - - view3d_project_float(ar, co1, vec1, mat); - view3d_project_float(ar, co2, vec2, mat); - mvalf[0]= (float)mval[0]; - mvalf[1]= (float)mval[1]; - - return PdistVL2Dfl(mvalf, vec1, vec2); -} - -/* helper for below */ -static void mesh_rip_setface(EditMesh *em, EditFace *sefa) -{ - /* put new vertices & edges in best face */ - if(sefa->v1->tmp.v) sefa->v1= sefa->v1->tmp.v; - if(sefa->v2->tmp.v) sefa->v2= sefa->v2->tmp.v; - if(sefa->v3->tmp.v) sefa->v3= sefa->v3->tmp.v; - if(sefa->v4 && sefa->v4->tmp.v) sefa->v4= sefa->v4->tmp.v; - - sefa->e1= addedgelist(em, sefa->v1, sefa->v2, sefa->e1); - sefa->e2= addedgelist(em, sefa->v2, sefa->v3, sefa->e2); - if(sefa->v4) { - sefa->e3= addedgelist(em, sefa->v3, sefa->v4, sefa->e3); - sefa->e4= addedgelist(em, sefa->v4, sefa->v1, sefa->e4); - } - else - sefa->e3= addedgelist(em, sefa->v3, sefa->v1, sefa->e3); - -} - -/* based on mouse cursor position, it defines how is being ripped */ -static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - ARegion *ar= CTX_wm_region(C); - RegionView3D *rv3d= ar->regiondata; - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - EditVert *eve, *nextve; - EditEdge *eed, *seed= NULL; - EditFace *efa, *sefa= NULL; - float projectMat[4][4], vec[3], dist, mindist; - short doit= 1, *mval= event->mval; - - /* select flush... vertices are important */ - EM_selectmode_set(em); - - view3d_get_object_project_mat(rv3d, obedit, projectMat); - - /* find best face, exclude triangles and break on face select or faces with 2 edges select */ - mindist= 1000000.0f; - for(efa= em->faces.first; efa; efa=efa->next) { - if( efa->f & 1) - break; - if(efa->v4 && faceselectedOR(efa, SELECT) ) { - int totsel=0; - - if(efa->e1->f & SELECT) totsel++; - if(efa->e2->f & SELECT) totsel++; - if(efa->e3->f & SELECT) totsel++; - if(efa->e4->f & SELECT) totsel++; - - if(totsel>1) - break; - view3d_project_float(ar, efa->cent, vec, projectMat); - dist= sqrt( (vec[0]-mval[0])*(vec[0]-mval[0]) + (vec[1]-mval[1])*(vec[1]-mval[1]) ); - if(dist<mindist) { - mindist= dist; - sefa= efa; - } - } - } - - if(efa) { - BKE_report(op->reports, RPT_ERROR, "Can't perform ripping with faces selected this way"); - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_CANCELLED; - } - if(sefa==NULL) { - BKE_report(op->reports, RPT_ERROR, "No proper selection or faces included"); - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_CANCELLED; - } - - - /* duplicate vertices, new vertices get selected */ - for(eve = em->verts.last; eve; eve= eve->prev) { - eve->tmp.v = NULL; - if(eve->f & SELECT) { - eve->tmp.v = addvertlist(em, eve->co, eve); - eve->f &= ~SELECT; - eve->tmp.v->f |= SELECT; - } - } - - /* find the best candidate edge */ - /* or one of sefa edges is selected... */ - if(sefa->e1->f & SELECT) seed= sefa->e2; - if(sefa->e2->f & SELECT) seed= sefa->e1; - if(sefa->e3->f & SELECT) seed= sefa->e2; - if(sefa->e4 && sefa->e4->f & SELECT) seed= sefa->e3; - - /* or we do the distance trick */ - if(seed==NULL) { - mindist= 1000000.0f; - if(sefa->e1->v1->tmp.v || sefa->e1->v2->tmp.v) { - dist = mesh_rip_edgedist(ar, projectMat, - sefa->e1->v1->co, - sefa->e1->v2->co, mval); - if(dist<mindist) { - seed= sefa->e1; - mindist= dist; - } - } - if(sefa->e2->v1->tmp.v || sefa->e2->v2->tmp.v) { - dist = mesh_rip_edgedist(ar, projectMat, - sefa->e2->v1->co, - sefa->e2->v2->co, mval); - if(dist<mindist) { - seed= sefa->e2; - mindist= dist; - } - } - if(sefa->e3->v1->tmp.v || sefa->e3->v2->tmp.v) { - dist= mesh_rip_edgedist(ar, projectMat, - sefa->e3->v1->co, - sefa->e3->v2->co, mval); - if(dist<mindist) { - seed= sefa->e3; - mindist= dist; - } - } - if(sefa->e4 && (sefa->e4->v1->tmp.v || sefa->e4->v2->tmp.v)) { - dist= mesh_rip_edgedist(ar, projectMat, - sefa->e4->v1->co, - sefa->e4->v2->co, mval); - if(dist<mindist) { - seed= sefa->e4; - mindist= dist; - } - } - } - - if(seed==NULL) { // never happens? - BKE_report(op->reports, RPT_ERROR, "No proper edge found to start"); - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_CANCELLED; - } - - faceloop_select(em, seed, 2); // tmp abuse for finding all edges that need duplicated, returns OK faces with f1 - - /* duplicate edges in the loop, with at least 1 vertex selected, needed for selection flip */ - for(eed = em->edges.last; eed; eed= eed->prev) { - eed->tmp.v = NULL; - if((eed->v1->tmp.v) || (eed->v2->tmp.v)) { - EditEdge *newed; - - newed= addedgelist(em, eed->v1->tmp.v?eed->v1->tmp.v:eed->v1, - eed->v2->tmp.v?eed->v2->tmp.v:eed->v2, eed); - if(eed->f & SELECT) { - EM_select_edge(eed, 0); - EM_remove_selection(em, eed, EDITEDGE); - EM_select_edge(newed, 1); - } - eed->tmp.v = (EditVert *)newed; - } - } - - /* first clear edges to help finding neighbours */ - for(eed = em->edges.last; eed; eed= eed->prev) eed->f1= 0; - - /* put new vertices & edges && flag in best face */ - mesh_rip_setface(em, sefa); - - /* starting with neighbours of best face, we loop over the seam */ - sefa->f1= 2; - doit= 1; - while(doit) { - doit= 0; - - for(efa= em->faces.first; efa; efa=efa->next) { - /* new vert in face */ - if (efa->v1->tmp.v || efa->v2->tmp.v || - efa->v3->tmp.v || (efa->v4 && efa->v4->tmp.v)) { - /* face is tagged with loop */ - if(efa->f1==1) { - mesh_rip_setface(em, efa); - efa->f1= 2; - doit= 1; - } - } - } - } - - /* remove loose edges, that were part of a ripped face */ - for(eve = em->verts.first; eve; eve= eve->next) eve->f1= 0; - for(eed = em->edges.last; eed; eed= eed->prev) eed->f1= 0; - for(efa= em->faces.first; efa; efa=efa->next) { - efa->e1->f1= 1; - efa->e2->f1= 1; - efa->e3->f1= 1; - if(efa->e4) efa->e4->f1= 1; - } - - for(eed = em->edges.last; eed; eed= seed) { - seed= eed->prev; - if(eed->f1==0) { - if(eed->v1->tmp.v || eed->v2->tmp.v || - (eed->v1->f & SELECT) || (eed->v2->f & SELECT)) { - remedge(em, eed); - free_editedge(em, eed); - eed= NULL; - } - } - if(eed) { - eed->v1->f1= 1; - eed->v2->f1= 1; - } - } - - /* and remove loose selected vertices, that got duplicated accidentally */ - for(eve = em->verts.first; eve; eve= nextve) { - nextve= eve->next; - if(eve->f1==0 && (eve->tmp.v || (eve->f & SELECT))) { - BLI_remlink(&em->verts,eve); - free_editvert(em, eve); - } - } - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - -// RNA_enum_set(op->ptr, "proportional", 0); -// RNA_boolean_set(op->ptr, "mirror", 0); -// WM_operator_name_call(C, "TFM_OT_translate", WM_OP_INVOKE_REGION_WIN, op->ptr); - - return OPERATOR_FINISHED; -} - -void MESH_OT_rip(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Rip"; - ot->description= "Rip selection from mesh (quads only)."; - ot->idname= "MESH_OT_rip"; - - /* api callbacks */ - ot->invoke= mesh_rip_invoke; - ot->poll= EM_view3d_poll; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* to give to transform */ - Properties_Proportional(ot); - RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", ""); -} - - /************************ Shape Operators *************************/ void shape_propagate(Scene *scene, Object *obedit, EditMesh *em, wmOperator *op) @@ -5068,6 +4289,7 @@ void shape_propagate(Scene *scene, Object *obedit, EditMesh *em, wmOperator *op) void shape_copy_from_lerp(EditMesh *em, KeyBlock* thisBlock, KeyBlock* fromBlock) { +#if 0 //BMESH_TODO EditVert *ev = NULL; short mval[2], curval[2], event = 0, finished = 0, canceled = 0, fullcopy=0 ; float perc = 0; @@ -5144,6 +4366,7 @@ void shape_copy_from_lerp(EditMesh *em, KeyBlock* thisBlock, KeyBlock* fromBlock } } return; +#endif } @@ -5643,7 +4866,7 @@ static void collapseuvs(EditMesh *em, EditVert *mergevert) } } -static int collapseEdges(EditMesh *em) +int collapseEdges(EditMesh *em) { EditVert *eve; EditEdge *eed; @@ -5709,406 +4932,7 @@ static int collapseEdges(EditMesh *em) return mergecount; } -static 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); -} - -static void em_snap_to_center(EditMesh *em) -{ - EditVert *eve; - float cent[3] = {0.0f, 0.0f, 0.0f}; - int i=0; - - for (eve=em->verts.first; eve; eve=eve->next) { - if (eve->f & SELECT) { - VecAddf(cent, cent, eve->co); - i++; - } - } - - if (!i) - return; - - VecMulf(cent, 1.0f / (float)i); - - for (eve=em->verts.first; eve; eve=eve->next) { - if (eve->f & SELECT) { - VECCOPY(eve->co, cent); - } - } -} - -static void em_snap_to_cursor(EditMesh *em, bContext *C) -{ - Scene *scene = CTX_data_scene(C); - Object *ob= CTX_data_edit_object(C); - View3D *v3d = CTX_wm_view3d(C); - EditVert *eve; - float co[3], *vco, invmat[4][4]; - - Mat4Invert(invmat, ob->obmat); - - vco = give_cursor(scene, v3d); - VECCOPY(co, vco); - Mat4MulVecfl(invmat, co); - - for (eve=em->verts.first; eve; eve=eve->next) { - if (eve->f & SELECT) { - VECCOPY(eve->co, co); - } - } -} - -static int merge_target(bContext *C, EditMesh *em, int target, int uvmerge) -{ - EditVert *eve; - - // XXX not working - if(target) em_snap_to_cursor(em, C); - else em_snap_to_center(em); - - 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) -{ - 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(C, em, 0, uvs); - break; - case 4: - count = merge_target(C, em, 1, uvs); - break; - case 1: - count = merge_firstlast(em, 0, uvs); - break; - case 6: - count = merge_firstlast(em, 1, uvs); - break; - case 5: - count = collapseEdges(em); - break; - } - - if(!count) - return OPERATOR_CANCELLED; - - BKE_reportf(op->reports, RPT_INFO, "Removed %d vertices.", count); - - BKE_mesh_end_editmesh(obedit->data, em); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - 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= CTX_data_edit_object(C); - EnumPropertyItem *item= NULL; - int totitem= 0; - - 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; -} - -void MESH_OT_merge(wmOperatorType *ot) -{ - PropertyRNA *prop; - - /* identifiers */ - ot->name= "Merge"; - ot->description= "Merge selected vertices."; - 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 { - int u; - int visited; - ListBase edges; -} PathNode; - -typedef struct PathEdge { - struct PathEdge *next, *prev; - int v; - float w; -} PathEdge; -#define PATH_SELECT_EDGE_LENGTH 0 -#define PATH_SELECT_TOPOLOGICAL 1 - -static int select_vertex_path_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - EditVert *eve, *s, *t; - EditEdge *eed; - EditSelection *ese; - PathEdge *newpe, *currpe; - PathNode *currpn; - PathNode *Q; - int v, *previous, pathvert, pnindex; /*pnindex redundant?*/ - int unbalanced, totnodes; - short physical; - float *cost; - Heap *heap; /*binary heap for sorting pointers to PathNodes based upon a 'cost'*/ - - s = t = NULL; - - ese = ((EditSelection*)em->selected.last); - if(ese && ese->type == EDITVERT && ese->prev && ese->prev->type == EDITVERT){ - physical= pupmenu("Distance Method? %t|Edge Length%x1|Topological%x0"); - - t = (EditVert*)ese->data; - s = (EditVert*)ese->prev->data; - - /*need to find out if t is actually reachable by s....*/ - for(eve=em->verts.first; eve; eve=eve->next){ - eve->f1 = 0; - } - - s->f1 = 1; - - unbalanced = 1; - totnodes = 1; - while(unbalanced){ - unbalanced = 0; - for(eed=em->edges.first; eed; eed=eed->next){ - if(!eed->h){ - if(eed->v1->f1 && !eed->v2->f1){ - eed->v2->f1 = 1; - totnodes++; - unbalanced = 1; - } - else if(eed->v2->f1 && !eed->v1->f1){ - eed->v1->f1 = 1; - totnodes++; - unbalanced = 1; - } - } - } - } - - if(s->f1 && t->f1){ /* t can be reached by s */ - Q = MEM_callocN(sizeof(PathNode)*totnodes, "Path Select Nodes"); - totnodes = 0; - for(eve=em->verts.first; eve; eve=eve->next){ - if(eve->f1){ - Q[totnodes].u = totnodes; - Q[totnodes].edges.first = 0; - Q[totnodes].edges.last = 0; - Q[totnodes].visited = 0; - eve->tmp.p = &(Q[totnodes]); - totnodes++; - } - else eve->tmp.p = NULL; - } - - for(eed=em->edges.first; eed; eed=eed->next){ - if(!eed->h){ - if(eed->v1->f1){ - currpn = ((PathNode*)eed->v1->tmp.p); - - newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge"); - newpe->v = ((PathNode*)eed->v2->tmp.p)->u; - if(physical){ - newpe->w = VecLenf(eed->v1->co, eed->v2->co); - } - else newpe->w = 1; - newpe->next = 0; - newpe->prev = 0; - BLI_addtail(&(currpn->edges), newpe); - } - if(eed->v2->f1){ - currpn = ((PathNode*)eed->v2->tmp.p); - newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge"); - newpe->v = ((PathNode*)eed->v1->tmp.p)->u; - if(physical){ - newpe->w = VecLenf(eed->v1->co, eed->v2->co); - } - else newpe->w = 1; - newpe->next = 0; - newpe->prev = 0; - BLI_addtail(&(currpn->edges), newpe); - } - } - } - - heap = BLI_heap_new(); - cost = MEM_callocN(sizeof(float)*totnodes, "Path Select Costs"); - previous = MEM_callocN(sizeof(int)*totnodes, "PathNode indices"); - - for(v=0; v < totnodes; v++){ - cost[v] = 1000000; - previous[v] = -1; /*array of indices*/ - } - - pnindex = ((PathNode*)s->tmp.p)->u; - cost[pnindex] = 0; - BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(pnindex)); - - while( !BLI_heap_empty(heap) ){ - - pnindex = GET_INT_FROM_POINTER(BLI_heap_popmin(heap)); - currpn = &(Q[pnindex]); - - if(currpn == (PathNode*)t->tmp.p) /*target has been reached....*/ - break; - - for(currpe=currpn->edges.first; currpe; currpe=currpe->next){ - if(!Q[currpe->v].visited){ - if( cost[currpe->v] > (cost[currpn->u ] + currpe->w) ){ - cost[currpe->v] = cost[currpn->u] + currpe->w; - previous[currpe->v] = currpn->u; - Q[currpe->v].visited = 1; - BLI_heap_insert(heap, cost[currpe->v], SET_INT_IN_POINTER(currpe->v)); - } - } - } - } - - pathvert = ((PathNode*)t->tmp.p)->u; - while(pathvert != -1){ - for(eve=em->verts.first; eve; eve=eve->next){ - if(eve->f1){ - if( ((PathNode*)eve->tmp.p)->u == pathvert) eve->f |= SELECT; - } - } - pathvert = previous[pathvert]; - } - - for(v=0; v < totnodes; v++) BLI_freelistN(&(Q[v].edges)); - MEM_freeN(Q); - MEM_freeN(cost); - MEM_freeN(previous); - BLI_heap_free(heap, NULL); - EM_select_flush(em); - } - } - else { - BKE_mesh_end_editmesh(obedit->data, em); - BKE_report(op->reports, RPT_ERROR, "Path Selection requires that exactly two vertices be selected"); - return OPERATOR_CANCELLED; - } - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); - - return OPERATOR_FINISHED; -} - -void MESH_OT_select_vertex_path(wmOperatorType *ot) -{ - static const EnumPropertyItem type_items[] = { - {PATH_SELECT_EDGE_LENGTH, "EDGE_LENGTH", 0, "Edge Length", NULL}, - {PATH_SELECT_TOPOLOGICAL, "TOPOLOGICAL", 0, "Topological", NULL}, - {0, NULL, 0, NULL, NULL}}; - - /* identifiers */ - ot->name= "Select Vertex Path"; - ot->description= "Select shortest path between two vertices by distance type."; - ot->idname= "MESH_OT_select_vertex_path"; - - /* api callbacks */ - ot->exec= select_vertex_path_exec; - ot->invoke= WM_menu_invoke; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* properties */ - RNA_def_enum(ot->srna, "type", type_items, PATH_SELECT_EDGE_LENGTH, "Type", "Method to compute distance."); -} /********************** Region/Loop Operators *************************/ @@ -6157,7 +4981,6 @@ void MESH_OT_region_to_loop(wmOperatorType *ot) { /* identifiers */ ot->name= "Region to Loop"; - ot->description= "Select a region as a loop of connected edges."; ot->idname= "MESH_OT_region_to_loop"; /* api callbacks */ @@ -6202,8 +5025,8 @@ static int validate_loop(EditMesh *em, Collection *edgecollection) return(1); } -static int loop_bisect(EditMesh *em, Collection *edgecollection){ - +static int loop_bisect(EditMesh *em, Collection *edgecollection) +{ EditFace *efa, *sf1, *sf2; EditEdge *eed, *sed; CollectedEdge *curredge; @@ -6333,7 +5156,6 @@ void MESH_OT_loop_to_region(wmOperatorType *ot) { /* identifiers */ ot->name= "Loop to Region"; - ot->description= "Select a loop of connected edges as a region."; ot->idname= "MESH_OT_loop_to_region"; /* api callbacks */ @@ -6344,403 +5166,6 @@ void MESH_OT_loop_to_region(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } -/********************** UV/Color Operators *************************/ - -// XXX please check if these functions do what you want them to -/* texface and vertex color editmode tools for the face menu */ - -static int mesh_rotate_uvs(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - - EditFace *efa; - short change = 0; - MTFace *tf; - float u1, v1; - int dir= RNA_enum_get(op->ptr, "direction"); - - if (!EM_texFaceCheck(em)) { - BKE_report(op->reports, RPT_ERROR, "Mesh has no uv/image layers."); - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_CANCELLED; - } - - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - u1= tf->uv[0][0]; - v1= tf->uv[0][1]; - - if (dir == DIRECTION_CCW) { - if(efa->v4) { - tf->uv[0][0]= tf->uv[3][0]; - tf->uv[0][1]= tf->uv[3][1]; - - tf->uv[3][0]= tf->uv[2][0]; - tf->uv[3][1]= tf->uv[2][1]; - } else { - tf->uv[0][0]= tf->uv[2][0]; - tf->uv[0][1]= tf->uv[2][1]; - } - - tf->uv[2][0]= tf->uv[1][0]; - tf->uv[2][1]= tf->uv[1][1]; - - tf->uv[1][0]= u1; - tf->uv[1][1]= v1; - } else { - tf->uv[0][0]= tf->uv[1][0]; - tf->uv[0][1]= tf->uv[1][1]; - - tf->uv[1][0]= tf->uv[2][0]; - tf->uv[1][1]= tf->uv[2][1]; - - if(efa->v4) { - tf->uv[2][0]= tf->uv[3][0]; - tf->uv[2][1]= tf->uv[3][1]; - - tf->uv[3][0]= u1; - tf->uv[3][1]= v1; - } - else { - tf->uv[2][0]= u1; - tf->uv[2][1]= v1; - } - } - change = 1; - } - } - - BKE_mesh_end_editmesh(obedit->data, em); - - if(!change) - return OPERATOR_CANCELLED; - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -static int mesh_mirror_uvs(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - - EditFace *efa; - short change = 0; - MTFace *tf; - float u1, v1; - int axis= RNA_enum_get(op->ptr, "axis"); - - if (!EM_texFaceCheck(em)) { - BKE_report(op->reports, RPT_ERROR, "Mesh has no uv/image layers."); - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_CANCELLED; - } - - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if (axis == AXIS_Y) { - u1= tf->uv[1][0]; - v1= tf->uv[1][1]; - if(efa->v4) { - - tf->uv[1][0]= tf->uv[2][0]; - tf->uv[1][1]= tf->uv[2][1]; - - tf->uv[2][0]= u1; - tf->uv[2][1]= v1; - - u1= tf->uv[3][0]; - v1= tf->uv[3][1]; - - tf->uv[3][0]= tf->uv[0][0]; - tf->uv[3][1]= tf->uv[0][1]; - - tf->uv[0][0]= u1; - tf->uv[0][1]= v1; - } - else { - tf->uv[1][0]= tf->uv[2][0]; - tf->uv[1][1]= tf->uv[2][1]; - tf->uv[2][0]= u1; - tf->uv[2][1]= v1; - } - - } else { - u1= tf->uv[0][0]; - v1= tf->uv[0][1]; - if(efa->v4) { - - tf->uv[0][0]= tf->uv[1][0]; - tf->uv[0][1]= tf->uv[1][1]; - - tf->uv[1][0]= u1; - tf->uv[1][1]= v1; - - u1= tf->uv[3][0]; - v1= tf->uv[3][1]; - - tf->uv[3][0]= tf->uv[2][0]; - tf->uv[3][1]= tf->uv[2][1]; - - tf->uv[2][0]= u1; - tf->uv[2][1]= v1; - } - else { - tf->uv[0][0]= tf->uv[1][0]; - tf->uv[0][1]= tf->uv[1][1]; - tf->uv[1][0]= u1; - tf->uv[1][1]= v1; - } - } - change = 1; - } - } - - BKE_mesh_end_editmesh(obedit->data, em); - - if(!change) - return OPERATOR_CANCELLED; - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -static int mesh_rotate_colors(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - - EditFace *efa; - short change = 0; - MCol tmpcol, *mcol; - int dir= RNA_enum_get(op->ptr, "direction"); - - if (!EM_vertColorCheck(em)) { - BKE_report(op->reports, RPT_ERROR, "Mesh has no color layers."); - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_CANCELLED; - } - - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT) { - mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); - tmpcol= mcol[0]; - - if (dir == DIRECTION_CCW) { - if(efa->v4) { - mcol[0]= mcol[3]; - mcol[3]= mcol[2]; - } else { - mcol[0]= mcol[2]; - } - mcol[2]= mcol[1]; - mcol[1]= tmpcol; - } else { - mcol[0]= mcol[1]; - mcol[1]= mcol[2]; - - if(efa->v4) { - mcol[2]= mcol[3]; - mcol[3]= tmpcol; - } - else - mcol[2]= tmpcol; - } - change = 1; - } - } - - BKE_mesh_end_editmesh(obedit->data, em); - - if(!change) - return OPERATOR_CANCELLED; - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - - -static int mesh_mirror_colors(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - - EditFace *efa; - short change = 0; - MCol tmpcol, *mcol; - int axis= RNA_enum_get(op->ptr, "axis"); - - if (!EM_vertColorCheck(em)) { - BKE_report(op->reports, RPT_ERROR, "Mesh has no color layers"); - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_CANCELLED; - } - - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT) { - mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); - if (axis == AXIS_Y) { - tmpcol= mcol[1]; - mcol[1]= mcol[2]; - mcol[2]= tmpcol; - - if(efa->v4) { - tmpcol= mcol[0]; - mcol[0]= mcol[3]; - mcol[3]= tmpcol; - } - } else { - tmpcol= mcol[0]; - mcol[0]= mcol[1]; - mcol[1]= tmpcol; - - if(efa->v4) { - tmpcol= mcol[2]; - mcol[2]= mcol[3]; - mcol[3]= tmpcol; - } - } - change = 1; - } - } - - BKE_mesh_end_editmesh(obedit->data, em); - - if(!change) - return OPERATOR_CANCELLED; - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -void MESH_OT_uvs_rotate(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Rotate UVs"; - ot->description= "Rotate selected UVs."; - ot->idname= "MESH_OT_uvs_rotate"; - - /* api callbacks */ - ot->exec= mesh_rotate_uvs; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate UVs around."); -} - -void MESH_OT_uvs_mirror(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Mirror UVs"; - ot->description= "Mirror selected UVs."; - ot->idname= "MESH_OT_uvs_mirror"; - - /* api callbacks */ - ot->exec= mesh_mirror_uvs; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror UVs around."); -} - -void MESH_OT_colors_rotate(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Rotate Colors"; - ot->description= "Rotate UV/image color layer."; - ot->idname= "MESH_OT_colors_rotate"; - - /* api callbacks */ - ot->exec= mesh_rotate_colors; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate edge around."); -} - -void MESH_OT_colors_mirror(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Mirror Colors"; - ot->description= "Mirror UV/image color layer."; - ot->idname= "MESH_OT_colors_mirror"; - - /* api callbacks */ - ot->exec= mesh_mirror_colors; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around."); -} - -/********************** Subdivide Operator *************************/ - -static int subdivide_exec(bContext *C, wmOperator *op) -{ - ToolSettings *ts= CTX_data_tool_settings(C); - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - int cuts= RNA_int_get(op->ptr,"number_cuts"); - float smooth= 0.292f*RNA_float_get(op->ptr, "smoothness"); - float fractal= RNA_float_get(op->ptr, "fractal")/100; - int flag= 0; - - if(smooth != 0.0f) - flag |= B_SMOOTH; - if(fractal != 0.0f) - flag |= B_FRACTAL; - - esubdivideflag(obedit, em, 1, smooth, fractal, ts->editbutflag|flag, cuts, 0); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -void MESH_OT_subdivide(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Subdivide"; - ot->description= "Subdivide selected edges."; - ot->idname= "MESH_OT_subdivide"; - - /* api callbacks */ - ot->exec= subdivide_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* properties */ - RNA_def_int(ot->srna, "number_cuts", 1, 1, 10, "Number of Cuts", "", 1, INT_MAX); - RNA_def_float(ot->srna, "fractal", 0.0, 0.0f, FLT_MAX, "Fractal", "Fractal randomness factor.", 0.0f, 1000.0f); - RNA_def_float(ot->srna, "smoothness", 0.0f, 0.0f, 1000.0f, "Smoothness", "Smoothness factor.", 0.0f, FLT_MAX); -} - /********************** Fill Operators *************************/ /* note; the EM_selectmode_set() calls here illustrate how badly constructed it all is... from before the @@ -7007,7 +5432,6 @@ void MESH_OT_fill(wmOperatorType *ot) { /* identifiers */ ot->name= "Fill"; - ot->description= "Create a segment, edge or face."; ot->idname= "MESH_OT_fill"; /* api callbacks */ @@ -7037,7 +5461,6 @@ void MESH_OT_beauty_fill(wmOperatorType *ot) { /* identifiers */ ot->name= "Beauty Fill"; - ot->description= "Arrange geometry on a selected surface to avoid skinny faces."; ot->idname= "MESH_OT_beauty_fill"; /* api callbacks */ @@ -7053,14 +5476,15 @@ void MESH_OT_beauty_fill(wmOperatorType *ot) static int quads_convert_to_tris_exec(bContext *C, wmOperator *op) { Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; - convert_to_triface(em,0); + //convert_to_triface(em,0); + if (!EDBM_CallOpf(em, op, "triangulate faces=%hf", BM_SELECT)) + return OPERATOR_CANCELLED; DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -7068,7 +5492,6 @@ void MESH_OT_quads_convert_to_tris(wmOperatorType *ot) { /* identifiers */ ot->name= "Quads to Tris"; - ot->description= "Convert selected quads to triangles."; ot->idname= "MESH_OT_quads_convert_to_tris"; /* api callbacks */ @@ -7097,7 +5520,6 @@ void MESH_OT_tris_convert_to_quads(wmOperatorType *ot) { /* identifiers */ ot->name= "Tris to Quads"; - ot->description= "Convert selected triangles to quads."; ot->idname= "MESH_OT_tris_convert_to_quads"; /* api callbacks */ @@ -7126,7 +5548,6 @@ void MESH_OT_edge_flip(wmOperatorType *ot) { /* identifiers */ ot->name= "Edge Flip"; - ot->description= "Flip selected edge or adjoining faces."; ot->idname= "MESH_OT_edge_flip"; /* api callbacks */ @@ -7136,78 +5557,3 @@ void MESH_OT_edge_flip(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } - -/********************** Smooth/Solid Operators *************************/ - -static void mesh_set_smooth_faces(EditMesh *em, short smooth) -{ - EditFace *efa; - - if(em==NULL) return; - - for(efa= em->faces.first; efa; efa=efa->next) { - if(efa->f & SELECT) { - if(smooth) efa->flag |= ME_SMOOTH; - else efa->flag &= ~ME_SMOOTH; - } - } -} - -static int mesh_faces_shade_smooth_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - - mesh_set_smooth_faces(em, 1); - - BKE_mesh_end_editmesh(obedit->data, em); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -void MESH_OT_faces_shade_smooth(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Shade Smooth"; - ot->description= "Display faces 'smooth' (using vertex normals)."; - ot->idname= "MESH_OT_faces_shade_smooth"; - - /* api callbacks */ - ot->exec= mesh_faces_shade_smooth_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - -static int mesh_faces_shade_flat_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - - mesh_set_smooth_faces(em, 0); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -void MESH_OT_faces_shade_flat(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Shade Flat"; - ot->description= "Display faces 'flat'."; - ot->idname= "MESH_OT_faces_shade_flat"; - - /* api callbacks */ - ot->exec= mesh_faces_shade_flat_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - diff --git a/source/blender/editors/mesh/loopcut.c b/source/blender/editors/mesh/loopcut.c index 4ef25238a84..9a2a953f643 100644 --- a/source/blender/editors/mesh/loopcut.c +++ b/source/blender/editors/mesh/loopcut.c @@ -47,6 +47,7 @@ #include "BLI_blenlib.h" #include "BLI_dynstr.h" /*for WM_operator_pystring */ #include "BLI_editVert.h" +#include "BLI_array.h" #include "BKE_blender.h" #include "BKE_context.h" @@ -54,6 +55,8 @@ #include "BKE_scene.h" #include "BKE_utildefines.h" #include "BKE_mesh.h" +#include "BKE_tessmesh.h" +#include "BKE_depsgraph.h" #include "BIF_gl.h" #include "BIF_glutil.h" /* for paint cursor */ @@ -90,8 +93,8 @@ typedef struct tringselOpData { ViewContext vc; Object *ob; - EditMesh *em; - EditEdge *eed; + BMEditMesh *em; + BMEdge *eed; int extend; int do_cut; @@ -122,13 +125,13 @@ static void ringsel_draw(const bContext *C, ARegion *ar, void *arg) static void edgering_sel(tringselOpData *lcd, int previewlines, int select) { - EditMesh *em = lcd->em; - EditEdge *startedge = lcd->eed; - EditEdge *eed; - EditFace *efa; - EditVert *v[2][2]; + BMEditMesh *em = lcd->em; + BMEdge *startedge = lcd->eed; + BMEdge *eed, *lasteed; + BMVert *v[2][2]; + BMWalker walker; float (*edges)[2][3] = NULL; - V_DYNDECLARE(edges); + BLI_array_declare(edges); float co[2][3]; int looking=1, i, tot=0; @@ -142,110 +145,104 @@ static void edgering_sel(tringselOpData *lcd, int previewlines, int select) } if (!lcd->extend) { - EM_clear_flag_all(lcd->em, SELECT); + EDBM_clear_flag_all(lcd->em, BM_SELECT); } - /* in eed->f1 we put the valence (amount of faces in edge) */ - /* in eed->f2 we put tagged flag as correct loop */ - /* in efa->f1 we put tagged flag as correct to select */ + if (select) { + BMW_Init(&walker, em->bm, BMW_EDGERING, 0, 0); + eed = BMW_Begin(&walker, startedge); + for (; eed; eed=BMW_Step(&walker)) { + BM_Select(em->bm, eed, 1); + } + BMW_End(&walker); - for(eed= em->edges.first; eed; eed= eed->next) { - eed->f1= 0; - eed->f2= 0; + return; } - for(efa= em->faces.first; efa; efa= efa->next) { - efa->f1= 0; - if(efa->h==0) { - efa->e1->f1++; - efa->e2->f1++; - efa->e3->f1++; - if(efa->e4) efa->e4->f1++; - } - } - - // tag startedge OK - startedge->f2= 1; - - while(looking) { - looking= 0; - - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->e4 && efa->f1==0 && efa->h == 0) { // not done quad - if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok - - // if edge tagged, select opposing edge and mark face ok - if(efa->e1->f2) { - efa->e3->f2= 1; - efa->f1= 1; - looking= 1; - } - else if(efa->e2->f2) { - efa->e4->f2= 1; - efa->f1= 1; - looking= 1; - } - if(efa->e3->f2) { - efa->e1->f2= 1; - efa->f1= 1; - looking= 1; - } - if(efa->e4->f2) { - efa->e2->f2= 1; - efa->f1= 1; - looking= 1; - } + BMW_Init(&walker, em->bm, BMW_EDGERING, 0, 0); + eed = startedge = BMW_Begin(&walker, startedge); + for (lasteed=NULL; eed; eed=BMW_Step(&walker)) { + if (lasteed) { + BMIter liter; + BMLoop *l, *l2; + int rev; + + v[0][0] = eed->v1; + v[0][1] = eed->v2; + v[1][0] = lasteed->v1; + v[1][1] = lasteed->v2; + +#if 0 //hrm. this code may be useful later. + /*find correct order for v[1]*/ + + l = eed->loop; + if (!(BM_Edge_In_Face(l->f, eed) && BM_Edge_In_Face(l->f, lasteed))) { + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_LOOP, l) { + if (BM_Edge_In_Face(l->f, eed) && BM_Edge_In_Face(l->f, lasteed)) + break; } } + + /*this should never happen*/ + if (!l) { + lasteed = eed; + continue; + } + + l2 = BM_OtherFaceLoop(l->e, l->f, l->v); + rev = (l2 == (BMLoop*)l->head.prev); + while (l2->v != lasteed->v1 && l2->v != lasteed->v2) { + l2 = rev ? (BMLoop*)l2->head.prev : (BMLoop*)l2->head.next; + } + + if (l2->v == lasteed->v1) { + v[1][0] = lasteed->v1; + v[1][1] = lasteed->v2; + } else { + v[1][0] = lasteed->v2; + v[1][1] = lasteed->v1; + } +#endif + for(i=1;i<=previewlines;i++){ + co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0]; + co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1]; + co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2]; + + co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0]; + co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1]; + co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2]; + + BLI_array_growone(edges); + VECCOPY(edges[tot][0], co[0]); + VECCOPY(edges[tot][1], co[1]); + tot++; + } } + lasteed = eed; } - if(previewlines > 0 && !select){ - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->v4 == NULL) { continue; } - if(efa->h == 0){ - if(efa->e1->f2 == 1){ - if(efa->e1->h == 1 || efa->e3->h == 1 ) - continue; - - v[0][0] = efa->v1; - v[0][1] = efa->v2; - v[1][0] = efa->v4; - v[1][1] = efa->v3; - } else if(efa->e2->f2 == 1){ - if(efa->e2->h == 1 || efa->e4->h == 1) - continue; - v[0][0] = efa->v2; - v[0][1] = efa->v3; - v[1][0] = efa->v1; - v[1][1] = efa->v4; - } else { continue; } - - for(i=1;i<=previewlines;i++){ - co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0]; - co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1]; - co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2]; - - co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0]; - co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1]; - co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2]; - - V_GROW(edges); - VECCOPY(edges[tot][0], co[0]); - VECCOPY(edges[tot][1], co[1]); - tot++; - } - } - } - } else { - select = (startedge->f & SELECT) == 0; - - /* select the edges */ - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f2) EM_select_edge(eed, select); + if (BM_Edge_Share_Faces(lasteed, startedge)) { + v[0][0] = startedge->v1; + v[0][1] = startedge->v2; + v[1][0] = lasteed->v1; + v[1][1] = lasteed->v2; + for(i=1;i<=previewlines;i++){ + co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0]; + co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1]; + co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2]; + + co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0]; + co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1]; + co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2]; + + BLI_array_growone(edges); + VECCOPY(edges[tot][0], co[0]); + VECCOPY(edges[tot][1], co[1]); + tot++; } } + BMW_End(&walker); lcd->edges = edges; lcd->totedge = tot; } @@ -264,9 +261,12 @@ static void ringsel_finish(bContext *C, wmOperator *op) if (lcd->eed) { edgering_sel(lcd, cuts, 1); if (lcd->do_cut) { - EditMesh *em = BKE_mesh_get_editmesh(lcd->ob->data); - esubdivideflag(lcd->ob, em, SELECT, 0.0f, 0.0f, 0, cuts, SUBDIV_SELECT_LOOPCUT); - + BMEditMesh *em = lcd->em; + BM_esubdivideflag(lcd->ob, em->bm, BM_SELECT, 0.0f, + 0.0f, 0, cuts, SUBDIV_SELECT_LOOPCUT, + SUBD_PATH, 0, 0); + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT|ND_DATA, lcd->ob->data); DAG_id_flush_update(lcd->ob->data, OB_RECALC_DATA); } WM_event_add_notifier(C, NC_GEOM|ND_DATA, lcd->ob->data); @@ -303,7 +303,7 @@ static int ringsel_init (bContext *C, wmOperator *op, int do_cut) lcd->ar= CTX_wm_region(C); lcd->draw_handle= ED_region_draw_cb_activate(lcd->ar->type, ringsel_draw, lcd, REGION_DRAW_POST); lcd->ob = CTX_data_edit_object(C); - lcd->em= BKE_mesh_get_editmesh((Mesh *)lcd->ob->data); + lcd->em= ((Mesh *)lcd->ob->data)->edit_btmesh; lcd->extend = do_cut ? 0 : RNA_boolean_get(op->ptr, "extend"); lcd->do_cut = do_cut; em_setup_viewcontext(C, &lcd->vc); @@ -323,7 +323,7 @@ static int ringsel_cancel (bContext *C, wmOperator *op) static int ringsel_invoke (bContext *C, wmOperator *op, wmEvent *evt) { tringselOpData *lcd; - EditEdge *edge; + BMEdge *edge; int dist = 75; view3d_operator_needs_opengl(C); @@ -338,7 +338,7 @@ static int ringsel_invoke (bContext *C, wmOperator *op, wmEvent *evt) lcd->vc.mval[0] = evt->mval[0]; lcd->vc.mval[1] = evt->mval[1]; - edge = findnearestedge(&lcd->vc, &dist); + edge = EDBM_findnearestedge(&lcd->vc, &dist); if (edge != lcd->eed) { lcd->eed = edge; ringsel_find_edge(lcd, C, lcd->ar, 1); @@ -351,7 +351,7 @@ static int ringsel_invoke (bContext *C, wmOperator *op, wmEvent *evt) static int ringcut_invoke (bContext *C, wmOperator *op, wmEvent *evt) { tringselOpData *lcd; - EditEdge *edge; + BMEdge *edge; int dist = 75; view3d_operator_needs_opengl(C); @@ -366,7 +366,7 @@ static int ringcut_invoke (bContext *C, wmOperator *op, wmEvent *evt) lcd->vc.mval[0] = evt->mval[0]; lcd->vc.mval[1] = evt->mval[1]; - edge = findnearestedge(&lcd->vc, &dist); + edge = EDBM_findnearestedge(&lcd->vc, &dist); if (edge != lcd->eed) { lcd->eed = edge; ringsel_find_edge(lcd, C, lcd->ar, 1); @@ -424,11 +424,11 @@ static int ringsel_modal (bContext *C, wmOperator *op, wmEvent *event) break; case MOUSEMOVE: { /* mouse moved somewhere to select another loop */ int dist = 75; - EditEdge *edge; + BMEdge *edge; lcd->vc.mval[0] = event->mval[0]; lcd->vc.mval[1] = event->mval[1]; - edge = findnearestedge(&lcd->vc, &dist); + edge = EDBM_findnearestedge(&lcd->vc, &dist); if (edge != lcd->eed) { lcd->eed = edge; diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 6ed2ca08c9c..848930e156b 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -48,6 +48,7 @@ #include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_report.h" +#include "BKE_tessmesh.h" #include "BLI_arithb.h" #include "BLI_editVert.h" @@ -68,12 +69,17 @@ static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *layer) { Mesh *me = ob->data; - CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata; + CustomData *data= (me->edit_btmesh)? &me->edit_btmesh->bm->pdata: &me->pdata; void *actlayerdata, *rndlayerdata, *clonelayerdata, *masklayerdata, *layerdata=layer->data; int type= layer->type; int index= CustomData_get_layer_index(data, type); - int i, actindex, rndindex, cloneindex, maskindex; + int i, actindex, rndindex, cloneindex, maskindex, tot = me->totpoly; + if (layer->type == CD_MLOOPCOL) { + data = (me->edit_btmesh)? &me->edit_btmesh->bm->ldata: &me->ldata; + tot = me->totloop; + } + /* ok, deleting a non-active layer needs to preserve the active layer indices. to do this, we store a pointer to the .data member of both layer and the active layer, (to detect if we're deleting the active layer or not), then use the active @@ -87,15 +93,15 @@ static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *la masklayerdata = data->layers[CustomData_get_mask_layer_index(data, type)].data; CustomData_set_layer_active(data, type, layer - &data->layers[index]); - if(me->edit_mesh) { - EM_free_data_layer(me->edit_mesh, data, type); + if(me->edit_btmesh) { + BM_free_data_layer(me->edit_btmesh->bm, data, type); } else { - CustomData_free_layer_active(data, type, me->totface); + CustomData_free_layer_active(data, type, tot); mesh_update_customdata_pointers(me); } - if(!CustomData_has_layer(data, type) && (type == CD_MCOL && (ob->mode & OB_MODE_VERTEX_PAINT))) + if(!CustomData_has_layer(data, type) && (type == CD_MLOOPCOL && (ob->mode & OB_MODE_VERTEX_PAINT))) ED_object_toggle_modes(C, OB_MODE_VERTEX_PAINT); /* reconstruct active layer */ @@ -158,30 +164,30 @@ static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *la int ED_mesh_uv_texture_add(bContext *C, Scene *scene, Object *ob, Mesh *me) { - EditMesh *em; + BMEditMesh *em; int layernum; - if(me->edit_mesh) { - em= me->edit_mesh; + if(me->edit_btmesh) { + em= me->edit_btmesh; - layernum= CustomData_number_of_layers(&em->fdata, CD_MTFACE); + layernum= CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY); if(layernum >= MAX_MTFACE) return OPERATOR_CANCELLED; - EM_add_data_layer(em, &em->fdata, CD_MTFACE); - CustomData_set_layer_active(&em->fdata, CD_MTFACE, layernum); + BM_add_data_layer(em->bm, &em->bm->pdata, MAX_MTFACE); + CustomData_set_layer_active(&em->bm->pdata, MAX_MTFACE, layernum); } else { - layernum= CustomData_number_of_layers(&me->fdata, CD_MTFACE); + layernum= CustomData_number_of_layers(&me->pdata, MAX_MTFACE); if(layernum >= MAX_MTFACE) return OPERATOR_CANCELLED; if(me->mtface) - CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface); + CustomData_add_layer(&me->pdata, MAX_MTFACE, CD_DUPLICATE, me->mtpoly, me->totpoly); else - CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface); + CustomData_add_layer(&me->pdata, MAX_MTFACE, CD_DEFAULT, NULL, me->totpoly); - CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum); + CustomData_set_layer_active(&me->pdata, MAX_MTFACE, layernum); mesh_update_customdata_pointers(me); } @@ -196,8 +202,8 @@ int ED_mesh_uv_texture_remove(bContext *C, Object *ob, Mesh *me) CustomDataLayer *cdl; int index; - index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE); - cdl= (index == -1)? NULL: &me->fdata.layers[index]; + index= CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY); + cdl= (index == -1)? NULL: &me->pdata.layers[index]; if(!cdl) return 0; @@ -211,37 +217,39 @@ int ED_mesh_uv_texture_remove(bContext *C, Object *ob, Mesh *me) int ED_mesh_color_add(bContext *C, Scene *scene, Object *ob, Mesh *me) { - EditMesh *em; - MCol *mcol; + BMEditMesh *em; + MLoopCol *mcol; int layernum; - if(me->edit_mesh) { - em= me->edit_mesh; + if(me->edit_btmesh) { + em= me->edit_btmesh; - layernum= CustomData_number_of_layers(&em->fdata, CD_MCOL); + layernum= CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL); if(layernum >= MAX_MCOL) return 0; - EM_add_data_layer(em, &em->fdata, CD_MCOL); - CustomData_set_layer_active(&em->fdata, CD_MCOL, layernum); + BM_add_data_layer(em->bm, &em->bm->pdata, CD_MLOOPCOL); + CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPCOL, layernum); } else { - layernum= CustomData_number_of_layers(&me->fdata, CD_MCOL); - if(layernum >= MAX_MCOL) + layernum= CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL); + if(layernum >= CD_MLOOPCOL) return 0; - mcol= me->mcol; + mcol= me->mloopcol; - if(me->mcol) - CustomData_add_layer(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface); + if(me->mloopcol) + CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DUPLICATE, me->mloopcol, me->totloop); else - CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface); + CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop); - CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum); + CustomData_set_layer_active(&me->ldata, CD_MLOOPCOL, layernum); mesh_update_customdata_pointers(me); + /*BMESH_TODO if(!mcol) shadeMeshMCol(scene, ob, me); + */ } DAG_id_flush_update(&me->id, OB_RECALC_DATA); @@ -255,8 +263,8 @@ int ED_mesh_color_remove(bContext *C, Object *ob, Mesh *me) CustomDataLayer *cdl; int index; - index= CustomData_get_active_layer_index(&me->fdata, CD_MCOL); - cdl= (index == -1)? NULL: &me->fdata.layers[index]; + index= CustomData_get_active_layer_index(&me->pdata, CD_MLOOPCOL); + cdl= (index == -1)? NULL: &me->pdata.layers[index]; if(!cdl) return 0; @@ -618,7 +626,7 @@ static void mesh_add_faces(Mesh *mesh, int len) void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges, int faces) { - if(mesh->edit_mesh) { + if(mesh->edit_btmesh) { BKE_report(reports, RPT_ERROR, "Can't add geometry in edit mode."); return; } diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 7ee7fe1ebde..4a1532af3b0 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -32,11 +32,53 @@ #ifndef MESH_INTERN_H #define MESH_INTERN_H +#include "BLI_editVert.h" +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" + struct bContext; struct wmOperatorType; +struct ViewContext; +struct BMEditMesh; +struct BMesh; +struct BMEdge; +struct BMFace; #define UVCOPY(t, s) memcpy(t, s, 2 * sizeof(float)); +/* ******************** bmeshutils.c */ + +/* +ok: the EDBM module is for editmode bmesh stuff. in contrast, the + BMEdit module is for code shared with blenkernel that concerns + the BMEditMesh structure. +*/ + +/*calls a bmesh op, reporting errors to the user, doing conversions, + etc.*/ +int EDBM_CallOpf(struct BMEditMesh *em, struct wmOperator *op, char *fmt, ...); + +/*same as above, but doesn't report errors.*/ +int EDBM_CallOpfSilent(struct BMEditMesh *em, char *fmt, ...); + +/*these next two functions are the split version of EDBM_CallOpf, so you can + do stuff with a bmesh operator, after initializing it but before executing + it. + + execute the operator with BM_Exec_Op*/ +int EDBM_InitOpf(struct BMEditMesh *em, struct BMOperator *bmop, + struct wmOperator *op, char *fmt, ...); +/*cleans up after a bmesh operator*/ +int EDBM_FinishOp(struct BMEditMesh *em, struct BMOperator *bmop, + struct wmOperator *op, int report); + +void EDBM_clear_flag_all(struct BMEditMesh *em, int flag); +void EDBM_store_selection(struct BMEditMesh *em, void *data); +void EDBM_validate_selections(struct BMEditMesh *em); +void EDBM_remove_selection(struct BMEditMesh *em, void *data); +void EDBM_stats_update(struct BMEditMesh *em); + /* ******************** editface.c */ int edgetag_context_check(Scene *scene, EditEdge *eed); @@ -45,11 +87,18 @@ int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge /* ******************* editmesh.c */ +void EM_beginEditMesh(struct Object *ob); +void EM_endEditMesh(struct Object *ob, EditMesh *em); + extern void free_editvert(EditMesh *em, EditVert *eve); extern void free_editedge(EditMesh *em, EditEdge *eed); extern void free_editface(EditMesh *em, EditFace *efa); void free_editMesh(EditMesh *em); +/*frees dst mesh, then copies the contents of + *src (the struct) to dst. */ +void set_editMesh(EditMesh *dst, EditMesh *src); + extern void free_vertlist(EditMesh *em, ListBase *edve); extern void free_edgelist(EditMesh *em, ListBase *lb); extern void free_facelist(EditMesh *em, ListBase *lb); @@ -61,7 +110,7 @@ extern struct EditEdge *addedgelist(EditMesh *em, struct EditVert *v1, struct Ed extern struct EditFace *addfacelist(EditMesh *em, struct EditVert *v1, struct EditVert *v2, struct EditVert *v3, struct EditVert *v4, struct EditFace *example, struct EditFace *exampleEdges); extern struct EditEdge *findedgelist(EditMesh *em, struct EditVert *v1, struct EditVert *v2); -void em_setup_viewcontext(struct bContext *C, ViewContext *vc); +void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc); void MESH_OT_separate(struct wmOperatorType *ot); @@ -143,12 +192,15 @@ void MESH_OT_knife_cut(struct wmOperatorType *ot); /* ******************* editmesh_mods.c */ void MESH_OT_loop_select(struct wmOperatorType *ot); void MESH_OT_select_all_toggle(struct wmOperatorType *ot); +void MESH_OT_bmesh_test(struct wmOperatorType *ot); void MESH_OT_select_more(struct wmOperatorType *ot); void MESH_OT_select_less(struct wmOperatorType *ot); void MESH_OT_select_inverse(struct wmOperatorType *ot); void MESH_OT_select_non_manifold(struct wmOperatorType *ot); void MESH_OT_select_linked(struct wmOperatorType *ot); void MESH_OT_select_linked_pick(struct wmOperatorType *ot); +void MESH_OT_pin(struct wmOperatorType *ot); +void MESH_OT_unpin(struct wmOperatorType *ot); void MESH_OT_hide(struct wmOperatorType *ot); void MESH_OT_reveal(struct wmOperatorType *ot); void MESH_OT_select_by_number_vertices(struct wmOperatorType *ot); @@ -166,13 +218,13 @@ void MESH_OT_mark_sharp(struct wmOperatorType *ot); void MESH_OT_vertices_smooth(struct wmOperatorType *ot); void MESH_OT_flip_normals(struct wmOperatorType *ot); -extern EditEdge *findnearestedge(ViewContext *vc, int *dist); +extern EditEdge *findnearestedge(struct ViewContext *vc, int *dist); extern void EM_automerge(Scene *scene, Object *obedit, int update); void editmesh_select_by_material(EditMesh *em, int index); void righthandfaces(EditMesh *em, int select); /* makes faces righthand turning */ void EM_select_more(EditMesh *em); void selectconnected_mesh_all(EditMesh *em); -void faceloop_select(EditMesh *em, EditEdge *startedge, int select); +void faceloop_select(struct BMEditMesh *em, struct BMEdge *startedge, int select); /** * findnearestvert @@ -183,7 +235,7 @@ void faceloop_select(EditMesh *em, EditEdge *startedge, int select); * if 0, unselected vertice are given the bias * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased */ -extern EditVert *findnearestvert(ViewContext *vc, int *dist, short sel, short strict); +extern EditVert *findnearestvert(struct ViewContext *vc, int *dist, short sel, short strict); /* ******************* editmesh_tools.c */ @@ -196,7 +248,7 @@ extern EditVert *findnearestvert(ViewContext *vc, int *dist, short sel, short st void join_triangles(EditMesh *em); int removedoublesflag(EditMesh *em, short flag, short automerge, float limit); /* return amount */ void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float fractal, int beauty, int numcuts, int seltype); -int EdgeSlide(EditMesh *em, wmOperator *op, short immediate, float imperc); +int EdgeSlide(EditMesh *em, struct wmOperator *op, short immediate, float imperc); void MESH_OT_merge(struct wmOperatorType *ot); void MESH_OT_subdivide(struct wmOperatorType *ot); @@ -220,9 +272,12 @@ void MESH_OT_loop_to_region(struct wmOperatorType *ot); void MESH_OT_region_to_loop(struct wmOperatorType *ot); void MESH_OT_uvs_rotate(struct wmOperatorType *ot); -void MESH_OT_uvs_mirror(struct wmOperatorType *ot); +//void MESH_OT_uvs_mirror(struct wmOperatorType *ot); +void MESH_OT_uvs_reverse(struct wmOperatorType *ot); void MESH_OT_colors_rotate(struct wmOperatorType *ot); -void MESH_OT_colors_mirror(struct wmOperatorType *ot); +//void MESH_OT_colors_mirror(struct wmOperatorType *ot); + +void MESH_OT_colors_reverse(struct wmOperatorType *ot); void MESH_OT_delete(struct wmOperatorType *ot); void MESH_OT_rip(struct wmOperatorType *ot); @@ -236,6 +291,15 @@ void MESH_OT_vertex_color_remove(struct wmOperatorType *ot); void MESH_OT_sticky_add(struct wmOperatorType *ot); 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); + void MESH_OT_edgering_select(struct wmOperatorType *ot); void MESH_OT_loopcut(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index c8d85aace47..7b2522ac3d2 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -77,6 +77,8 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_select_linked_pick); WM_operatortype_append(MESH_OT_select_random); WM_operatortype_append(MESH_OT_selection_type); + WM_operatortype_append(MESH_OT_pin); + WM_operatortype_append(MESH_OT_unpin); WM_operatortype_append(MESH_OT_hide); WM_operatortype_append(MESH_OT_reveal); WM_operatortype_append(MESH_OT_select_by_number_vertices); @@ -112,9 +114,11 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_region_to_loop); WM_operatortype_append(MESH_OT_uvs_rotate); - WM_operatortype_append(MESH_OT_uvs_mirror); + //WM_operatortype_append(MESH_OT_uvs_mirror); + WM_operatortype_append(MESH_OT_uvs_reverse); WM_operatortype_append(MESH_OT_colors_rotate); - WM_operatortype_append(MESH_OT_colors_mirror); + //WM_operatortype_append(MESH_OT_colors_mirror); + WM_operatortype_append(MESH_OT_colors_reverse); WM_operatortype_append(MESH_OT_fill); WM_operatortype_append(MESH_OT_beauty_fill); @@ -146,7 +150,16 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_vertex_color_remove); WM_operatortype_append(MESH_OT_sticky_add); WM_operatortype_append(MESH_OT_sticky_remove); + 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); + WM_operatortype_append(MESH_OT_edgering_select); WM_operatortype_append(MESH_OT_loopcut); } @@ -173,10 +186,16 @@ void ED_operatormacros_mesh(void) otmacro= WM_operatortype_macro_define(ot, "TFM_OT_translate"); RNA_enum_set(otmacro->ptr, "proportional", 0); - ot= WM_operatortype_append_macro("MESH_OT_extrude_move", "Extrude", OPTYPE_UNDO|OPTYPE_REGISTER); + /*ot= WM_operatortype_append_macro("MESH_OT_extrude_move", "Extrude", OPTYPE_UNDO|OPTYPE_REGISTER); WM_operatortype_macro_define(ot, "MESH_OT_extrude"); otmacro= WM_operatortype_macro_define(ot, "TFM_OT_translate"); RNA_enum_set(otmacro->ptr, "proportional", 0); + 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? */ @@ -203,11 +222,14 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MESH_OT_select_shortest_path", SELECTMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "MESH_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "MESH_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "MESH_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "MESH_OT_select_inverse", IKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "MESH_OT_select_non_manifold", MKEY, KM_PRESS, (KM_CTRL|KM_SHIFT|KM_ALT), 0); - + + WM_keymap_add_item(keymap, "MESH_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "MESH_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "MESH_OT_select_more", EQUALKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "MESH_OT_select_less", MINUSKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "MESH_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "MESH_OT_select_linked_pick", LKEY, KM_PRESS, 0, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_select_linked_pick", LKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "deselect", 1); @@ -216,12 +238,19 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) RNA_float_set(WM_keymap_add_item(keymap, "MESH_OT_edges_select_sharp", SKEY, KM_PRESS, (KM_CTRL|KM_SHIFT|KM_ALT), 0)->ptr,"sharpness",135.0); WM_keymap_add_item(keymap, "MESH_OT_vertices_transform_to_sphere", SKEY, KM_PRESS, KM_CTRL|KM_SHIFT , 0); - WM_keymap_add_item(keymap, "MESH_OT_select_similar", GKEY, KM_PRESS, KM_SHIFT, 0); + + WM_keymap_add_item(keymap, "MESH_OT_edge_split", MKEY, KM_PRESS, 0, 0); /* selection mode */ WM_keymap_add_item(keymap, "MESH_OT_selection_type", TABKEY, KM_PRESS, KM_CTRL, 0); + /* pin */ + WM_keymap_add_item(keymap, "MESH_OT_pin", RETKEY, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_pin", RETKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "unselected", 1); + WM_keymap_add_item(keymap, "MESH_OT_unpin", RETKEY, KM_PRESS, KM_ALT, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_unpin", RETKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0)->ptr, "unselected", 1); + /* hide */ WM_keymap_add_item(keymap, "MESH_OT_hide", HKEY, KM_PRESS, 0, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "unselected", 1); @@ -231,7 +260,9 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MESH_OT_normals_make_consistent", NKEY, KM_PRESS, KM_CTRL, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_normals_make_consistent", NKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0)->ptr, "inside", 1); - WM_keymap_add_item(keymap, "MESH_OT_extrude_move", EKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "MESH_OT_extrude", EKEY, KM_PRESS, 0, 0); + + WM_keymap_add_item(keymap, "MESH_OT_vert_connect", YKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "MESH_OT_spin", RKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "MESH_OT_screw", NINEKEY, KM_PRESS, KM_CTRL, 0); @@ -250,11 +281,13 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MESH_OT_region_to_loop",SIXKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "MESH_OT_uvs_rotate",SEVENKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "MESH_OT_uvs_mirror",SEVENKEY, KM_PRESS, KM_ALT, 0); + //WM_keymap_add_item(keymap, "MESH_OT_uvs_mirror",SEVENKEY, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "MESH_OT_uvs_reverse",SEVENKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "MESH_OT_colors_rotate",EIGHTKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "MESH_OT_colors_mirror",EIGHTKEY, KM_PRESS, KM_ALT, 0); + //WM_keymap_add_item(keymap, "MESH_OT_colors_mirror",EIGHTKEY, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "MESH_OT_colors_reverse",EIGHTKEY, KM_PRESS, KM_ALT, 0); - WM_keymap_add_item(keymap, "MESH_OT_rip_move",VKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "MESH_OT_rip_move",VKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "MESH_OT_merge", MKEY, KM_PRESS, KM_ALT, 0); /* add/remove */ diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index fad73e19e16..629e7bacc20 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -73,6 +73,7 @@ #include "BKE_object.h" #include "BKE_utildefines.h" #include "BKE_report.h" +#include "BKE_tessmesh.h" #include "RE_pipeline.h" #include "RE_shader_ext.h" @@ -119,15 +120,17 @@ int join_mesh_exec(bContext *C, wmOperator *op) MVert *mvert, *mv, *mvertmain; MEdge *medge = NULL, *medgemain; MFace *mface = NULL, *mfacemain; + MPoly *mpoly = NULL, *mpolymain; + MLoop *mloop = NULL, *mloopmain; Key *key, *nkey=NULL; KeyBlock *kb, *okb, *kbn; float imat[4][4], cmat[4][4], *fp1, *fp2, curpos; int a, b, totcol, totmat=0, totedge=0, totvert=0, totface=0, ok=0; - int vertofs, *matmap; - int i, j, index, haskey=0, edgeofs, faceofs; + int totloop=0, totpoly=0, vertofs, *matmap; + int i, j, index, haskey=0, edgeofs, faceofs, loopofs, polyofs; bDeformGroup *dg, *odg; MDeformVert *dvert; - CustomData vdata, edata, fdata; + CustomData vdata, edata, fdata, ldata, pdata; if(scene->obedit) return OPERATOR_CANCELLED; @@ -144,6 +147,8 @@ int join_mesh_exec(bContext *C, wmOperator *op) totvert+= me->totvert; totedge+= me->totedge; totface+= me->totface; + totloop+= me->totloop; + totpoly+= me->totpoly; totmat+= base->object->totcol; if(base->object == ob) @@ -291,18 +296,26 @@ int join_mesh_exec(bContext *C, wmOperator *op) memset(&vdata, 0, sizeof(vdata)); memset(&edata, 0, sizeof(edata)); memset(&fdata, 0, sizeof(fdata)); + memset(&ldata, 0, sizeof(ldata)); + memset(&pdata, 0, sizeof(pdata)); mvert= CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert); medge= CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); mface= CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface); + mloop= CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloop); + mpoly= CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, NULL, totpoly); mvertmain= mvert; medgemain= medge; mfacemain= mface; + mloopmain = mloop; + mpolymain = mpoly; vertofs= 0; edgeofs= 0; faceofs= 0; + loopofs= 0; + polyofs= 0; /* inverse transform for all selected meshes in this object */ Mat4Invert(imat, ob->obmat); @@ -452,7 +465,43 @@ int join_mesh_exec(bContext *C, wmOperator *op) edgeofs += me->totedge; } + + if (me->totloop) { + CustomData_merge(&me->ldata, &ldata, CD_MASK_MESH, CD_DEFAULT, totloop); + CustomData_copy_data(&me->ldata, &ldata, 0, loopofs, me->totloop); + + for(a=0; a<me->totloop; a++, mloop++) { + mloop->v += vertofs; + mloop->e += edgeofs; + } + + loopofs += me->totloop; + } + if(me->totpoly) { + /* make mapping for materials */ + for(a=1; a<=base->object->totcol; a++) { + ma= give_current_material(base->object, a); + + for(b=0; b<totcol; b++) { + if(ma == matar[b]) { + matmap[a-1]= b; + break; + } + } + } + + CustomData_merge(&me->pdata, &pdata, CD_MASK_MESH, CD_DEFAULT, totpoly); + CustomData_copy_data(&me->pdata, &pdata, 0, polyofs, me->totpoly); + + for(a=0; a<me->totpoly; a++, mpoly++) { + mpoly->loopstart += loopofs; + mpoly->mat_nr= matmap[(int)mpoly->mat_nr]; + } + + polyofs += me->totface; + } + /* vertofs is used to help newly added verts be reattached to their edge/face * (cannot be set earlier, or else reattaching goes wrong) */ @@ -471,14 +520,20 @@ int join_mesh_exec(bContext *C, wmOperator *op) CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->edata, me->totedge); CustomData_free(&me->fdata, me->totface); + CustomData_free(&me->ldata, me->totloop); + CustomData_free(&me->pdata, me->totpoly); me->totvert= totvert; me->totedge= totedge; me->totface= totface; + me->totloop= totloop; + me->totpoly= totpoly; me->vdata= vdata; me->edata= edata; me->fdata= fdata; + me->ldata= ldata; + me->pdata= pdata; mesh_update_customdata_pointers(me); @@ -839,7 +894,7 @@ static struct { /* mode is 's' start, or 'e' end, or 'u' use */ /* if end, ob can be NULL */ -intptr_t mesh_octree_table(Object *ob, EditMesh *em, float *co, char mode) +intptr_t mesh_octree_table(Object *ob, BMEditMesh *em, float *co, char mode) { MocNode **bt; @@ -865,10 +920,12 @@ intptr_t mesh_octree_table(Object *ob, EditMesh *em, float *co, char mode) * we are using the undeformed coordinates*/ INIT_MINMAX(min, max); - if(em && me->edit_mesh==em) { - EditVert *eve; + if(em && me->edit_btmesh==em) { + BMIter iter; + BMVert *eve; - for(eve= em->verts.first; eve; eve= eve->next) + eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL); + for (; eve; eve=BMIter_Step(&iter)) DO_MINMAX(eve->co, min, max) } else { @@ -906,10 +963,12 @@ intptr_t mesh_octree_table(Object *ob, EditMesh *em, float *co, char mode) MeshOctree.table= MEM_callocN(MOC_RES*MOC_RES*MOC_RES*sizeof(void *), "sym table"); - if(em && me->edit_mesh==em) { - EditVert *eve; + if(em && me->edit_btmesh==em) { + BMVert *eve; + BMIter iter; - for(eve= em->verts.first; eve; eve= eve->next) { + eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL); + for (; eve; eve=BMIter_Step(&iter)) { mesh_octree_add_nodes(MeshOctree.table, eve->co, MeshOctree.offs, MeshOctree.div, (intptr_t)(eve)); } } @@ -965,7 +1024,7 @@ int mesh_get_x_mirror_vert(Object *ob, int index) return mesh_octree_table(ob, NULL, vec, 'u'); } -EditVert *editmesh_get_x_mirror_vert(Object *ob, EditMesh *em, float *co) +BMVert *editmesh_get_x_mirror_vert(Object *ob, BMEditMesh *em, float *co) { float vec[3]; intptr_t poinval; @@ -983,7 +1042,7 @@ EditVert *editmesh_get_x_mirror_vert(Object *ob, EditMesh *em, float *co) poinval= mesh_octree_table(ob, em, vec, 'u'); if(poinval != -1) - return (EditVert *)(poinval); + return (BMVert *)(poinval); return NULL; } @@ -1033,7 +1092,7 @@ static int mirror_facecmp(void *a, void *b) return (mirror_facerotation((MFace*)a, (MFace*)b) == -1); } -int *mesh_get_x_mirror_faces(Object *ob, EditMesh *em) +int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em) { Mesh *me= ob->data; MVert *mv, *mvert= me->mvert; diff --git a/source/blender/editors/object/SConscript b/source/blender/editors/object/SConscript index 6ecc80f2d81..a6f034c9c33 100644 --- a/source/blender/editors/object/SConscript +++ b/source/blender/editors/object/SConscript @@ -6,7 +6,7 @@ sources = env.Glob('*.c') incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc' incs += ' #/intern/guardedalloc' -incs += ' ../../makesrna ../../python ../../ikplugin' +incs += ' ../../makesrna ../../python ../../ikplugin ../../bmesh' defs = [] diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index bd8b865a6c9..08689e9b62b 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -112,6 +112,7 @@ #include "BKE_texture.h" #include "BKE_utildefines.h" #include "BKE_modifier.h" +#include "BKE_tessmesh.h" #include "ED_anim_api.h" #include "ED_armature.h" @@ -297,16 +298,17 @@ void ED_object_exit_editmode(bContext *C, int flag) // if(retopo_mesh_paint_check()) // retopo_end_okee(); - if(me->edit_mesh->totvert>MESH_MAX_VERTS) { + if(me->edit_btmesh->bm->totvert>MESH_MAX_VERTS) { error("Too many vertices"); return; } - load_editMesh(scene, obedit); + + EDBM_LoadEditBMesh(scene, obedit); if(freedata) { - free_editMesh(me->edit_mesh); - MEM_freeN(me->edit_mesh); - me->edit_mesh= NULL; + EDBM_FreeEditBMesh(me->edit_btmesh); + MEM_freeN(me->edit_btmesh); + me->edit_btmesh= NULL; } if(obedit->restore_mode & OB_MODE_WEIGHT_PAINT) @@ -336,21 +338,10 @@ void ED_object_exit_editmode(bContext *C, int flag) /* freedata only 0 now on file saves and render */ if(freedata) { - ListBase pidlist; - PTCacheID *pid; - /* for example; displist make is different in editmode */ scene->obedit= NULL; // XXX for context - - /* flag object caches as outdated */ - BKE_ptcache_ids_from_object(&pidlist, obedit); - for(pid=pidlist.first; pid; pid=pid->next) { - if(pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */ - pid->cache->flag |= PTCACHE_OUTDATED; - } - BLI_freelistN(&pidlist); - BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED); + BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_DEPSGRAPH); /* also flush ob recalc, doesn't take much overhead, but used for particles */ DAG_id_flush_update(&obedit->id, OB_RECALC_OB|OB_RECALC_DATA); @@ -410,7 +401,7 @@ void ED_object_enter_editmode(bContext *C, int flag) ok= 1; scene->obedit= ob; // context sees this - make_editMesh(scene, ob); + EDBM_MakeEditBMesh(CTX_data_tool_settings(C), scene, ob); WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_MESH, scene); } @@ -1965,26 +1956,29 @@ static int object_mode_set_compat(bContext *C, wmOperator *op, Object *ob) ObjectMode mode = RNA_enum_get(op->ptr, "mode"); if(ob) { - if(mode == OB_MODE_OBJECT) - return 1; - switch(ob->type) { + case OB_EMPTY: + case OB_LAMP: + case OB_CAMERA: + if(mode & OB_MODE_OBJECT) + return 1; + return 0; case OB_MESH: - if(mode & (OB_MODE_EDIT|OB_MODE_SCULPT|OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT|OB_MODE_PARTICLE_EDIT)) + if(mode & ( OB_MODE_OBJECT|OB_MODE_EDIT|OB_MODE_SCULPT|OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT|OB_MODE_PARTICLE_EDIT)) return 1; return 0; case OB_CURVE: case OB_SURF: case OB_FONT: case OB_MBALL: - if(mode & (OB_MODE_EDIT)) + if(mode & (OB_MODE_OBJECT|OB_MODE_EDIT)) return 1; return 0; case OB_LATTICE: - if(mode & (OB_MODE_EDIT|OB_MODE_WEIGHT_PAINT)) + if(mode & (OB_MODE_OBJECT|OB_MODE_EDIT|OB_MODE_WEIGHT_PAINT)) return 1; case OB_ARMATURE: - if(mode & (OB_MODE_EDIT|OB_MODE_POSE)) + if(mode & (OB_MODE_OBJECT|OB_MODE_EDIT|OB_MODE_POSE)) return 1; } } @@ -2000,7 +1994,7 @@ static int object_mode_set_exec(bContext *C, wmOperator *op) int toggle = RNA_boolean_get(op->ptr, "toggle"); if(!ob || !object_mode_set_compat(C, op, ob)) - return OPERATOR_PASS_THROUGH; + return OPERATOR_CANCELLED; /* Exit current mode if it's not the mode we're setting */ if(ob->mode != OB_MODE_OBJECT && ob->mode != mode) @@ -2041,7 +2035,7 @@ void OBJECT_OT_mode_set(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - prop= RNA_def_enum(ot->srna, "mode", object_mode_items, OB_MODE_OBJECT, "Mode", ""); + prop= RNA_def_enum(ot->srna, "mode", object_mode_items, 0, "Mode", ""); RNA_def_enum_funcs(prop, object_mode_set_itemsf); RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", ""); diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index dd3e5969a75..94a5ad6fa9f 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -44,7 +44,7 @@ #include "DNA_windowmanager_types.h" #include "BLI_blenlib.h" -#include "BLI_editVert.h" +#include "BLI_cellalloc.h" #include "BKE_context.h" #include "BKE_customdata.h" @@ -57,6 +57,7 @@ #include "BKE_mesh.h" #include "BKE_paint.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "RNA_access.h" #include "RNA_define.h" @@ -112,10 +113,10 @@ MDeformWeight *ED_vgroup_weight_verify(MDeformVert *dv, int defgroup) if(newdw) return newdw; - newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight"); + newdw = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight"); if(dv->dw) { memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight); - MEM_freeN(dv->dw); + BLI_cellalloc_free(dv->dw); } dv->dw=newdw; @@ -218,13 +219,13 @@ void ED_vgroup_nr_vert_remove(Object *ob, int def_nr, int vertnum) * deform weight, and reshuffle the others */ if(dvert->totweight) { - newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), + newdw = BLI_cellalloc_malloc(sizeof(MDeformWeight)*(dvert->totweight), "deformWeight"); if(dvert->dw){ memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i); memcpy(newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i)); - MEM_freeN(dvert->dw); + BLI_cellalloc_free(dvert->dw); } dvert->dw=newdw; } @@ -317,11 +318,11 @@ void ED_vgroup_nr_vert_add(Object *ob, int def_nr, int vertnum, float weight, in /* if we are doing an additive assignment, then * we need to create the deform weight */ - newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), + newdw = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight"); if(dv->dw){ memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight); - MEM_freeN(dv->dw); + BLI_cellalloc_free(dv->dw); } dv->dw=newdw; @@ -390,10 +391,11 @@ void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum) ED_vgroup_nr_vert_remove(ob, def_nr, vertnum); } + static float get_vert_def_nr(Object *ob, int def_nr, int vertnum) { MDeformVert *dvert= NULL; - EditVert *eve; + BMVert *eve; Mesh *me; int i; @@ -401,10 +403,10 @@ static float get_vert_def_nr(Object *ob, int def_nr, int vertnum) if(ob->type==OB_MESH) { me= ob->data; - if(me->edit_mesh) { - eve= BLI_findlink(&me->edit_mesh->verts, vertnum); + if(me->edit_btmesh) { + eve= BMIter_AtIndex(me->edit_btmesh->bm, BM_VERTS_OF_MESH, NULL, vertnum); if(!eve) return 0.0f; - dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT); + dvert= CustomData_bmesh_get(&me->edit_btmesh->bm->vdata, eve->head.data, CD_MDEFORMVERT); vertnum= 0; } else @@ -461,33 +463,30 @@ void ED_vgroup_select_by_name(Object *ob, char *name) /* only in editmode */ static void vgroup_select_verts(Object *ob, int select) { - EditVert *eve; + BMVert *eve; MDeformVert *dvert; int i; if(ob->type == OB_MESH) { Mesh *me= ob->data; - EditMesh *em = BKE_mesh_get_editmesh(me); + BMEditMesh *em = me->edit_btmesh; + BMIter iter; - for(eve=em->verts.first; eve; eve=eve->next){ - dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT); if(dvert && dvert->totweight){ for(i=0; i<dvert->totweight; i++){ if(dvert->dw[i].def_nr == (ob->actdef-1)){ - if(select) eve->f |= SELECT; - else eve->f &= ~SELECT; - + BM_Select(em->bm, eve, select); break; } } } } /* this has to be called, because this function operates on vertices only */ - if(select) EM_select_flush(em); // vertices to edges/faces - else EM_deselect_flush(em); - - BKE_mesh_end_editmesh(me, em); + if(select) EDBM_selectmode_flush(em); // vertices to edges/faces + else EDBM_deselect_flush(em); } else if(ob->type == OB_LATTICE) { Lattice *lt= vgroup_edit_lattice(ob); @@ -686,12 +685,11 @@ static void vgroup_delete_object_mode(Object *ob) /* Remove the group */ BLI_freelinkN(&ob->defbase, dg); } - /* only in editmode */ /* removes from active defgroup, if allverts==0 only selected vertices */ static void vgroup_active_remove_verts(Object *ob, int allverts) { - EditVert *eve; + BMVert *eve; MDeformVert *dvert; MDeformWeight *newdw; bDeformGroup *dg, *eg; @@ -703,19 +701,20 @@ static void vgroup_active_remove_verts(Object *ob, int allverts) if(ob->type == OB_MESH) { Mesh *me= ob->data; - EditMesh *em = BKE_mesh_get_editmesh(me); + BMEditMesh *em = me->edit_btmesh; + BMIter iter; - for(eve=em->verts.first; eve; eve=eve->next){ - dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT); - if(dvert && dvert->dw && ((eve->f & 1) || allverts)){ + if(dvert && dvert->dw && (BM_TestHFlag(eve, BM_SELECT) || allverts)){ for(i=0; i<dvert->totweight; i++){ /* Find group */ eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr); if(eg == dg){ dvert->totweight--; - if(dvert->totweight){ - newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), "deformWeight"); + if (dvert->totweight){ + newdw = BLI_cellalloc_malloc (sizeof(MDeformWeight)*(dvert->totweight), "deformWeight"); if(dvert->dw){ memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i); @@ -725,7 +724,7 @@ static void vgroup_active_remove_verts(Object *ob, int allverts) dvert->dw=newdw; } else{ - MEM_freeN(dvert->dw); + BLI_cellalloc_free (dvert->dw); dvert->dw=NULL; break; } @@ -733,7 +732,6 @@ static void vgroup_active_remove_verts(Object *ob, int allverts) } } } - BKE_mesh_end_editmesh(me, em); } else if(ob->type == OB_LATTICE) { Lattice *lt= vgroup_edit_lattice(ob); @@ -768,19 +766,19 @@ static void vgroup_delete_edit_mode(Object *ob) /* Make sure that any verts with higher indices are adjusted accordingly */ if(ob->type==OB_MESH) { Mesh *me= ob->data; - EditMesh *em = BKE_mesh_get_editmesh(me); - EditVert *eve; + BMEditMesh *em = me->edit_btmesh; + BMIter iter; + BMVert *eve; MDeformVert *dvert; - for(eve=em->verts.first; eve; eve=eve->next){ - dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT); if(dvert) for(i=0; i<dvert->totweight; i++) if(dvert->dw[i].def_nr > (ob->actdef-1)) dvert->dw[i].def_nr--; } - BKE_mesh_end_editmesh(me, em); } else if(ob->type==OB_LATTICE) { Lattice *lt= vgroup_edit_lattice(ob); @@ -828,7 +826,7 @@ static void vgroup_delete_edit_mode(Object *ob) static int vgroup_object_in_edit_mode(Object *ob) { if(ob->type == OB_MESH) - return (((Mesh*)ob->data)->edit_mesh != NULL); + return (((Mesh*)ob->data)->edit_btmesh != NULL); else if(ob->type == OB_LATTICE) return (((Lattice*)ob->data)->editlatt != NULL); @@ -869,7 +867,7 @@ static void vgroup_delete_all(Object *ob) /* only in editmode */ static void vgroup_assign_verts(Object *ob, float weight) { - EditVert *eve; + BMVert *eve; bDeformGroup *dg, *eg; MDeformWeight *newdw; MDeformVert *dvert; @@ -879,16 +877,17 @@ static void vgroup_assign_verts(Object *ob, float weight) if(ob->type == OB_MESH) { Mesh *me= ob->data; - EditMesh *em = BKE_mesh_get_editmesh(me); + BMEditMesh *em = me->edit_btmesh; + BMIter iter; - if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) - EM_add_data_layer(em, &em->vdata, CD_MDEFORMVERT); + if(!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT)) + BM_add_data_layer(em->bm, &em->bm->vdata, CD_MDEFORMVERT); /* Go through the list of editverts and assign them */ - for(eve=em->verts.first; eve; eve=eve->next){ - dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT); - if(dvert && (eve->f & 1)){ + if(dvert && BM_TestHFlag(eve, BM_SELECT)) { done=0; /* See if this vert already has a reference to this group */ /* If so: Change its weight */ @@ -904,10 +903,10 @@ static void vgroup_assign_verts(Object *ob, float weight) } /* If not: Add the group and set its weight */ if(!done){ - newdw = MEM_callocN(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight"); + newdw = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight"); if(dvert->dw){ memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight); - MEM_freeN(dvert->dw); + BLI_cellalloc_free(dvert->dw); } dvert->dw=newdw; @@ -919,7 +918,6 @@ static void vgroup_assign_verts(Object *ob, float weight) } } } - BKE_mesh_end_editmesh(me, em); } else if(ob->type == OB_LATTICE) { Lattice *lt= vgroup_edit_lattice(ob); @@ -1320,4 +1318,3 @@ void OBJECT_OT_vertex_group_menu(wmOperatorType *ot) ot->poll= vertex_group_poll; ot->exec= vertex_group_menu_exec; } - diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 74ed6451d29..a1570810e94 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -1024,7 +1024,7 @@ static void recalc_emitter_field(Object *ob, ParticleSystem *psys) BLI_kdtree_free(edit->emitter_field); - totface=dm->getNumFaces(dm); + totface=dm->getNumTessFaces(dm); totvert=dm->getNumVerts(dm); edit->emitter_cosnos=MEM_callocN(totface*6*sizeof(float),"emitter cosnos"); @@ -1036,7 +1036,7 @@ static void recalc_emitter_field(Object *ob, ParticleSystem *psys) mvert=dm->getVertDataArray(dm,CD_MVERT); for(i=0; i<totface; i++, vec+=6, nor+=6) { - mface=dm->getFaceData(dm,i,CD_MFACE); + mface=dm->getTessFaceData(dm,i,CD_MFACE); mvert=dm->getVertData(dm,mface->v1,CD_MVERT); VECCOPY(vec,mvert->co); diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 1dc08a162b7..fd81e828bea 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -562,7 +562,7 @@ static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) continue; } - mface = CDDM_get_face(dm,nearest.index); + mface = CDDM_get_tessface(dm,nearest.index); VecCopyf(v[0], CDDM_get_vert(dm,mface->v1)->co); VecCopyf(v[1], CDDM_get_vert(dm,mface->v2)->co); diff --git a/source/blender/editors/render/SConscript b/source/blender/editors/render/SConscript index bddc5ed10e0..3e1e99a7a6a 100644 --- a/source/blender/editors/render/SConscript +++ b/source/blender/editors/render/SConscript @@ -7,7 +7,7 @@ incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' #/intern/guardedalloc ../../gpu' incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern' -incs += ' ../../blenloader' +incs += ' ../../blenloader ../../bmesh' if env['OURPLATFORM'] == 'linux2': cflags='-pthread' diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index a9023194271..e03a118e86e 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -51,6 +51,7 @@ #include "BKE_texture.h" #include "BKE_utildefines.h" #include "BKE_world.h" +#include "BKE_tessmesh.h" #include "BLI_arithb.h" #include "BLI_editVert.h" @@ -278,13 +279,15 @@ static int material_slot_assign_exec(bContext *C, wmOperator *op) if(ob && ob->actcol>0) { if(ob->type == OB_MESH) { - EditMesh *em= ((Mesh*)ob->data)->edit_mesh; - EditFace *efa; + BMEditMesh *em= ((Mesh*)ob->data)->edit_btmesh; + BMFace *efa; + BMIter iter; if(em) { - for(efa= em->faces.first; efa; efa=efa->next) - if(efa->f & SELECT) + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if(BM_TestHFlag(efa, BM_SELECT)) efa->mat_nr= ob->actcol-1; + } } } else if(ELEM(ob->type, OB_CURVE, OB_SURF)) { @@ -336,14 +339,15 @@ static int material_slot_de_select(bContext *C, int select) return OPERATOR_CANCELLED; if(ob->type == OB_MESH) { - EditMesh *em= ((Mesh*)ob->data)->edit_mesh; - + BMEditMesh *em= ((Mesh*)ob->data)->edit_btmesh; +/*BMESH_TODO if(em) { if(select) EM_select_by_material(em, ob->actcol-1); else EM_deselect_by_material(em, ob->actcol-1); } +*/ } else if ELEM(ob->type, OB_CURVE, OB_SURF) { ListBase *editnurb= ((Curve*)ob->data)->editnurb; diff --git a/source/blender/editors/screen/Makefile b/source/blender/editors/screen/Makefile index 00698917be5..c88e53f5f97 100644 --- a/source/blender/editors/screen/Makefile +++ b/source/blender/editors/screen/Makefile @@ -42,6 +42,7 @@ CPPFLAGS += -I$(OPENGL_HEADERS) CPPFLAGS += -I../../windowmanager CPPFLAGS += -I../../blenloader CPPFLAGS += -I../../blenkernel +CPPFLAGS += -I../../bmesh CPPFLAGS += -I../../blenlib CPPFLAGS += -I../../makesdna CPPFLAGS += -I../../makesrna diff --git a/source/blender/editors/screen/SConscript b/source/blender/editors/screen/SConscript index 847a1cddfb4..97ce70ad71d 100644 --- a/source/blender/editors/screen/SConscript +++ b/source/blender/editors/screen/SConscript @@ -5,7 +5,7 @@ sources = env.Glob('*.c') incs = '../include ../../blenlib ../../blenkernel ../../blenfont ../../makesdna ../../imbuf' incs += ' ../../blenloader ../../windowmanager ../../python ../../makesrna' -incs += ' ../../render/extern/include' +incs += ' ../../render/extern/include ../../bmesh' incs += ' #/intern/guardedalloc #/extern/glew/include' defs = '' diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index eeddeee25bf..fe29b574cf0 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -57,6 +57,7 @@ #include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "BKE_sound.h" #include "WM_api.h" @@ -214,7 +215,7 @@ int ED_operator_editmesh(bContext *C) { Object *obedit= CTX_data_edit_object(C); if(obedit && obedit->type==OB_MESH) - return NULL != ((Mesh *)obedit->data)->edit_mesh; + return NULL != ((Mesh *)obedit->data)->edit_btmesh; return 0; } @@ -241,36 +242,27 @@ int ED_operator_posemode(bContext *C) int ED_operator_uvedit(bContext *C) { Object *obedit= CTX_data_edit_object(C); - EditMesh *em= NULL; + BMEditMesh *em= NULL; if(obedit && obedit->type==OB_MESH) - em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - - if(em && (em->faces.first) && (CustomData_has_layer(&em->fdata, CD_MTFACE))) { - BKE_mesh_end_editmesh(obedit->data, em); + em= ((Mesh *)obedit->data)->edit_btmesh; + if (em && em->bm->totface && CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY)) return 1; - } - if(obedit) - BKE_mesh_end_editmesh(obedit->data, em); return 0; } int ED_operator_uvmap(bContext *C) { Object *obedit= CTX_data_edit_object(C); - EditMesh *em= NULL; + BMEditMesh *em= NULL; if(obedit && obedit->type==OB_MESH) - em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + em= ((Mesh *)obedit->data)->edit_btmesh; - if(em && (em->faces.first)) { - BKE_mesh_end_editmesh(obedit->data, em); + if(em && (em->bm->totface)) return 1; - } - if(obedit) - BKE_mesh_end_editmesh(obedit->data, em); return 0; } @@ -2224,7 +2216,7 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event) ScreenAnimData *sad= wt->customdata; ScrArea *sa; int sync; - + /* sync, don't sync, or follow scene setting */ if(sad->flag & ANIMPLAY_FLAG_SYNC) sync= 1; else if(sad->flag & ANIMPLAY_FLAG_NO_SYNC) sync= 0; @@ -2233,7 +2225,7 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event) if(sync) { /* skip frames */ int step = floor(wt->duration * FPS); - if(sad->flag & ANIMPLAY_FLAG_REVERSE) // XXX does this option work with audio? + if (sad->flag & ANIMPLAY_FLAG_REVERSE) // XXX does this option work with audio? scene->r.cfra -= step; else scene->r.cfra += step; @@ -2241,7 +2233,7 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event) } else { /* one frame +/- */ - if(sad->flag & ANIMPLAY_FLAG_REVERSE) + if (sad->flag & ANIMPLAY_FLAG_REVERSE) scene->r.cfra--; else scene->r.cfra++; @@ -2283,7 +2275,7 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event) /* since we follow drawflags, we can't send notifier but tag regions ourselves */ ED_update_for_newframe(C, 1); - + sound_update_playing(C); for(sa= screen->areabase.first; sa; sa= sa->next) { @@ -2333,7 +2325,7 @@ static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event) ScrArea *sa= CTX_wm_area(C); int mode= (RNA_boolean_get(op->ptr, "reverse")) ? -1 : 1; int sync= -1; - + if(RNA_property_is_set(op->ptr, "sync")) sync= (RNA_boolean_get(op->ptr, "sync")); @@ -2345,7 +2337,7 @@ static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event) /* update region if TIME_REGION was set, to leftmost 3d window */ ED_screen_animation_timer_update(C, stime->redraws); - } + } else { int redraws = TIME_REGION|TIME_ALL_3D_WIN; diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 7596191e781..6118fdb4a02 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -2956,11 +2956,11 @@ static void project_paint_begin(ProjPaintState *ps) } ps->dm_mvert = ps->dm->getVertArray(ps->dm); - ps->dm_mface = ps->dm->getFaceArray(ps->dm); - ps->dm_mtface= ps->dm->getFaceDataArray(ps->dm, CD_MTFACE); + ps->dm_mface = ps->dm->getTessFaceArray(ps->dm); + ps->dm_mtface= ps->dm->getTessFaceDataArray(ps->dm, CD_MTFACE); ps->dm_totvert = ps->dm->getNumVerts(ps->dm); - ps->dm_totface = ps->dm->getNumFaces(ps->dm); + ps->dm_totface = ps->dm->getNumTessFaces(ps->dm); /* use clone mtface? */ diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 13fbd2179b8..9a2ce42e7db 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -90,9 +90,9 @@ static void imapaint_tri_weights(Object *ob, float *v1, float *v2, float *v3, fl void imapaint_pick_uv(Scene *scene, Object *ob, Mesh *mesh, unsigned int faceindex, int *xy, float *uv) { DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); - int *index = dm->getFaceDataArray(dm, CD_ORIGINDEX); - MTFace *tface = dm->getFaceDataArray(dm, CD_MTFACE), *tf; - int numfaces = dm->getNumFaces(dm), a; + int *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + MTFace *tface = dm->getTessFaceDataArray(dm, CD_MTFACE), *tf; + int numfaces = dm->getNumTessFaces(dm), a; float p[2], w[3], absw, minabsw; MFace mf; MVert mv[4]; @@ -103,7 +103,7 @@ void imapaint_pick_uv(Scene *scene, Object *ob, Mesh *mesh, unsigned int faceind /* test all faces in the derivedmesh with the original index of the picked face */ for(a = 0; a < numfaces; a++) { if(index[a] == faceindex) { - dm->getFace(dm, a, &mf); + dm->getTessFace(dm, a, &mf); dm->getVert(dm, mf.v1, &mv[0]); dm->getVert(dm, mf.v2, &mv[1]); diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 5afc4954c9c..4a45df9eb91 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -43,7 +43,8 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" - +#include "BLI_memarena.h" +#include "BLI_cellalloc.h" #include "DNA_action_types.h" #include "DNA_armature_types.h" @@ -203,7 +204,7 @@ static unsigned int vpaint_get_current_col(VPaint *vp) return rgba_to_mcol(brush->rgb[0], brush->rgb[1], brush->rgb[2], 1.0f); } -void do_shared_vertexcol(Mesh *me) +static void do_shared_vertex_tesscol(Mesh *me) { /* if no mcol: do not do */ /* if tface: only the involved faces, otherwise all */ @@ -269,6 +270,63 @@ void do_shared_vertexcol(Mesh *me) MEM_freeN(scolmain); } +void do_shared_vertexcol(Mesh *me) +{ + MLoop *ml = me->mloop; + MLoopCol *lcol = me->mloopcol; + MTexPoly *mtp = me->mtpoly; + MPoly *mp = me->mpoly; + float (*scol)[5]; + int i; + + /* if no mloopcol: do not do */ + /* if mtexpoly: only the involved faces, otherwise all */ + + if(me->mloopcol==0 || me->totvert==0 || me->totpoly==0) return; + + scol = MEM_callocN(sizeof(float)*me->totvert*5, "scol"); + + for (i=0; i<me->totloop; i++, ml++, lcol++) { + if (i >= mp->loopstart + mp->totloop) { + mp++; + if (mtp) mtp++; + } + + if (mtp && !(mtp->mode & TF_SHAREDCOL)) + continue; + + scol[ml->v][0] += lcol->r; + scol[ml->v][1] += lcol->g; + scol[ml->v][2] += lcol->b; + scol[ml->v][3] += lcol->a; + scol[ml->v][4] += 1.0; + } + + for (i=0; i<me->totvert; i++) { + if (!scol[i][4]) continue; + + scol[i][0] /= scol[i][4]; + scol[i][1] /= scol[i][4]; + scol[i][2] /= scol[i][4]; + scol[i][3] /= scol[i][4]; + } + + ml = me->mloop; + lcol = me->mloopcol; + for (i=0; i<me->totloop; i++, ml++, lcol++) { + if (!scol[ml->v][4]) continue; + + lcol->r = scol[ml->v][0]; + lcol->g = scol[ml->v][1]; + lcol->b = scol[ml->v][2]; + lcol->a = scol[ml->v][3]; + } + + MEM_freeN(scol); + + do_shared_vertex_tesscol(me); +} + void make_vertexcol(Scene *scene, int shade) /* single ob */ { Object *ob; @@ -285,21 +343,26 @@ void make_vertexcol(Scene *scene, int shade) /* single ob */ if(me==0) return; /* copies from shadedisplist to mcol */ - if(!me->mcol) { - CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface); - mesh_update_customdata_pointers(me); - } + if(!me->mcol) + CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface); + if (!me->mloopcol) + CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop); + + mesh_update_customdata_pointers(me); + + /* if(shade) shadeMeshMCol(scene, ob, me); else memset(me->mcol, 255, 4*sizeof(MCol)*me->totface); - + */ + DAG_id_flush_update(&me->id, OB_RECALC_DATA); } -static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot) +static void copy_vpaint_prev(VPaint *vp, unsigned int *lcol, int tot) { if(vp->vpaint_prev) { MEM_freeN(vp->vpaint_prev); @@ -307,10 +370,10 @@ static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot) } vp->tot= tot; - if(mcol==NULL || tot==0) return; + if(lcol==NULL || tot==0) return; - vp->vpaint_prev= MEM_mallocN(4*sizeof(int)*tot, "vpaint_prev"); - memcpy(vp->vpaint_prev, mcol, 4*sizeof(int)*tot); + vp->vpaint_prev= MEM_mallocN(sizeof(int)*tot, "vpaint_prev"); + memcpy(vp->vpaint_prev, lcol, sizeof(int)*tot); } @@ -333,10 +396,12 @@ static void copy_wpaint_prev (VPaint *wp, MDeformVert *dverts, int dcount) void clear_vpaint(Scene *scene, int selected) { Mesh *me; - MFace *mf; + MFace *mf; + MPoly *mp; + MLoopCol *lcol; Object *ob; unsigned int paintcol, *mcol; - int i; + int i, j; ob= OBACT; me= get_mesh(ob); @@ -357,6 +422,18 @@ void clear_vpaint(Scene *scene, int selected) mcol[3] = paintcol; } } + + mp = me->mpoly; + lcol = me->mloopcol; + for (i=0; i<me->totpoly; i++, mp++) { + if (!(!selected || mp->flag & ME_FACE_SEL)) + continue; + + lcol = me->mloopcol + mp->loopstart; + for (j=0; j<mp->totloop; j++, lcol++) { + *(int*)lcol = paintcol; + } + } DAG_id_flush_update(&me->id, OB_RECALC_DATA); } @@ -853,13 +930,14 @@ static void wpaint_blend(VPaint *wp, MDeformWeight *dw, MDeformWeight *uw, float /* else */ /* sets wp->weight to the closest weight value to vertex */ /* note: we cant sample frontbuf, weight colors are interpolated too unpredictable */ +#if 0 void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode) { ViewContext vc; ToolSettings *ts= scene->toolsettings; Object *ob= OBACT; Mesh *me= get_mesh(ob); - int index; + int index, i; short mval[2], sco[2]; if (!me) return; @@ -867,13 +945,13 @@ void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode) // getmouseco_areawin(mval); index= view3d_sample_backbuf(&vc, mval[0], mval[1]); - if(index && index<=me->totface) { - MFace *mface; - - mface= ((MFace *)me->mface) + index-1; + if(index && index<=me->totpoly) { + MPoly *mpoly; + mpoly= ((MPoly *)me->mpoly) + index-1; if(mode==1) { /* sampe which groups are in here */ MDeformVert *dv; + MLoop *ml; int a, totgroup; totgroup= BLI_countlist(&ob->defbase); @@ -881,28 +959,14 @@ void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode) int totmenu=0; int *groups=MEM_callocN(totgroup*sizeof(int), "groups"); - dv= me->dvert+mface->v1; - for(a=0; a<dv->totweight; a++) { - if (dv->dw[a].def_nr<totgroup) - groups[dv->dw[a].def_nr]= 1; - } - dv= me->dvert+mface->v2; - for(a=0; a<dv->totweight; a++) { + ml = me->mloop+mpoly->loopstart; + for (i=0; i<mpoly->totloop; i++, ml++) { + dv = me->dvert+ml->v; if (dv->dw[a].def_nr<totgroup) groups[dv->dw[a].def_nr]= 1; + } - dv= me->dvert+mface->v3; - for(a=0; a<dv->totweight; a++) { - if (dv->dw[a].def_nr<totgroup) - groups[dv->dw[a].def_nr]= 1; - } - if(mface->v4) { - dv= me->dvert+mface->v4; - for(a=0; a<dv->totweight; a++) { - if (dv->dw[a].def_nr<totgroup) - groups[dv->dw[a].def_nr]= 1; - } - } + for(a=0; a<totgroup; a++) if(groups[a]) totmenu++; @@ -936,28 +1000,19 @@ void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode) else { DerivedMesh *dm; MDeformWeight *dw; - float w1, w2, w3, w4, co[3], fac; + MLoop *ml; + float w, co[3], fmin = 10000000.0f; + int loopi = mpoly->loopstart; dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); if(dm->getVertCo==NULL) { //notice("Not supported yet"); } else { - /* calc 3 or 4 corner weights */ - dm->getVertCo(dm, mface->v1, co); - project_short_noclip(ar, co, sco); - w1= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1])); - - dm->getVertCo(dm, mface->v2, co); - project_short_noclip(ar, co, sco); - w2= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1])); - - dm->getVertCo(dm, mface->v3, co); - project_short_noclip(ar, co, sco); - w3= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1])); - - if(mface->v4) { - dm->getVertCo(dm, mface->v4, co); + /* find minimum distance */ + ml = me->mloop + mpoly->loopstart; + for (i=0; i<mpoly->totloop; i++, ml++) { + dm->getVertCo(dm, ml->v, co); project_short_noclip(ar, co, sco); w4= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1])); } @@ -980,8 +1035,13 @@ void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode) if(mface->v4) { dw= ED_vgroup_weight_get(me->dvert+mface->v4, ob->actdef-1); if(dw) ts->vgroup_weight= dw->weight; else ts->vgroup_weight= 0.0f; +>>>>>>> .merge-right.r23146 } } + + ml = me->mloop + loopi; + dw= get_defweight(me->dvert+ml->v, ob->actdef-1); + if(dw) ts->vgroup_weight= dw->weight; else ts->vgroup_weight= 0.0f; } dm->release(dm); } @@ -989,6 +1049,7 @@ void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode) } } +#endif static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index, int alpha, float paintweight, int vgroup_mirror) { @@ -1230,6 +1291,13 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *event) me= get_mesh(ob); if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH; + /*we can't assume mfaces have a correct origindex layer that indices to mpolys. + so instead we have to regenerate the tesselation faces altogether.*/ + me->totface = mesh_recalcTesselation(&me->fdata, &me->ldata, &me->pdata, + me->mvert, me->totface, me->totloop, me->totpoly); + mesh_update_customdata_pointers(me); + makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH); + /* if nothing was added yet, we make dverts and a vertex deform group */ if (!me->dvert) ED_vgroup_data_create(&me->id); @@ -1351,22 +1419,22 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P if(wp->flag & VP_COLINDEX) { for(index=0; index<totindex; index++) { - if(indexar[index] && indexar[index]<=me->totface) { - MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); + if(indexar[index] && indexar[index]<=me->totpoly) { + MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1); - if(mface->mat_nr!=ob->actcol-1) { + if(mpoly->mat_nr!=ob->actcol-1) { indexar[index]= 0; } } } } - if((G.f & G_FACESELECT) && me->mface) { + if((G.f & G_FACESELECT) && me->mpoly) { for(index=0; index<totindex; index++) { - if(indexar[index] && indexar[index]<=me->totface) { - MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); + if(indexar[index] && indexar[index]<=me->totpoly) { + MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1); - if((mface->flag & ME_FACE_SEL)==0) { + if((mpoly->flag & ME_FACE_SEL)==0) { indexar[index]= 0; } } @@ -1382,13 +1450,14 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P paintweight= ts->vgroup_weight; for(index=0; index<totindex; index++) { - if(indexar[index] && indexar[index]<=me->totface) { - MFace *mface= me->mface + (indexar[index]-1); - - (me->dvert+mface->v1)->flag= 1; - (me->dvert+mface->v2)->flag= 1; - (me->dvert+mface->v3)->flag= 1; - if(mface->v4) (me->dvert+mface->v4)->flag= 1; + if(indexar[index] && indexar[index]<=me->totpoly) { + MPoly *mpoly= me->mpoly + (indexar[index]-1); + MLoop *ml = me->mloop + mpoly->loopstart; + int i; + + for (i=0; i<mpoly->totloop; i++, ml++) { + (me->dvert+ml->v)->flag = 1; + } if(wp->mode==VP_BLUR) { MDeformWeight *dw, *(*dw_func)(MDeformVert *, int) = ED_vgroup_weight_verify; @@ -1396,15 +1465,13 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P if(wp->flag & VP_ONLYVGROUP) dw_func= ED_vgroup_weight_get; - dw= dw_func(me->dvert+mface->v1, ob->actdef-1); - if(dw) {paintweight+= dw->weight; totw++;} - dw= dw_func(me->dvert+mface->v2, ob->actdef-1); - if(dw) {paintweight+= dw->weight; totw++;} - dw= dw_func(me->dvert+mface->v3, ob->actdef-1); - if(dw) {paintweight+= dw->weight; totw++;} - if(mface->v4) { - dw= dw_func(me->dvert+mface->v4, ob->actdef-1); - if(dw) {paintweight+= dw->weight; totw++;} + ml = me->mloop + mpoly->loopstart; + for (i=0; i<mpoly->totloop; i++, ml++) { + dw = dw_func(me->dvert+ml->v, ob->actdef-1); + if (dw) { + paintweight += dw->weight; + totw++; + } } } } @@ -1415,40 +1482,18 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P for(index=0; index<totindex; index++) { - if(indexar[index] && indexar[index]<=me->totface) { - MFace *mface= me->mface + (indexar[index]-1); - - if((me->dvert+mface->v1)->flag) { - alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v1, mval); - if(alpha) { - do_weight_paint_vertex(wp, ob, mface->v1, alpha, paintweight, wpd->vgroup_mirror); - } - (me->dvert+mface->v1)->flag= 0; - } - - if((me->dvert+mface->v2)->flag) { - alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v2, mval); - if(alpha) { - do_weight_paint_vertex(wp, ob, mface->v2, alpha, paintweight, wpd->vgroup_mirror); - } - (me->dvert+mface->v2)->flag= 0; - } - - if((me->dvert+mface->v3)->flag) { - alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v3, mval); - if(alpha) { - do_weight_paint_vertex(wp, ob, mface->v3, alpha, paintweight, wpd->vgroup_mirror); - } - (me->dvert+mface->v3)->flag= 0; - } - - if((me->dvert+mface->v4)->flag) { - if(mface->v4) { - alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v4, mval); + if(indexar[index] && indexar[index]<=me->totpoly) { + MPoly *mpoly= me->mpoly + (indexar[index]-1); + MLoop *ml=me->mloop+mpoly->loopstart; + int i; + + for (i=0; i<mpoly->totloop; i++, ml++) { + if ((me->dvert+ml->v)->flag) { + alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*ml->v, mval); if(alpha) { - do_weight_paint_vertex(wp, ob, mface->v4, alpha, paintweight, wpd->vgroup_mirror); + do_weight_paint_vertex(wp, ob, ml->v, alpha, paintweight, wpd->vgroup_mirror); } - (me->dvert+mface->v4)->flag= 0; + (me->dvert+ml->v)->flag= 0; } } } @@ -1551,7 +1596,7 @@ static int set_vpaint(bContext *C, wmOperator *op) /* toggle */ return OPERATOR_FINISHED; } - if(me && me->mcol==NULL) make_vertexcol(scene, 0); + if(me && me->mloopcol==NULL) make_vertexcol(scene, 0); /* toggle: end vpaint */ if(ob->mode & OB_MODE_VERTEX_PAINT) { @@ -1620,14 +1665,60 @@ For future: */ +typedef struct polyfacemap_e { + struct polyfacemap_e *next, *prev; + int facenr; +} polyfacemap_e; + typedef struct VPaintData { ViewContext vc; unsigned int paintcol; int *indexar; float *vertexcosnos; float vpimat[3][3]; + + /*mpoly -> mface mapping*/ + MemArena *arena; + ListBase *polyfacemap; } VPaintData; +static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me, + Object *ob, Scene *scene) +{ + MFace *mf; + polyfacemap_e *e; + int *origIndex; + int i; + + vd->arena = BLI_memarena_new(1<<13); + BLI_memarena_use_calloc(vd->arena); + + vd->polyfacemap = BLI_memarena_alloc(vd->arena, sizeof(ListBase)*me->totpoly); + + /*we can't assume mfaces have a correct origindex layer that indices to mpolys. + so instead we have to regenerate the tesselation faces altogether.*/ + me->totface = mesh_recalcTesselation(&me->fdata, &me->ldata, &me->pdata, + me->mvert, me->totface, me->totloop, me->totpoly); + mesh_update_customdata_pointers(me); + makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH); + + origIndex = CustomData_get_layer(&me->fdata, CD_ORIGINDEX); + mf = me->mface; + + if (!origIndex) + return; + + for (i=0; i<me->totface; i++, mf++, origIndex++) { + if (*origIndex == ORIGINDEX_NONE) + continue; + + e = BLI_memarena_alloc(vd->arena, sizeof(polyfacemap_e)); + e->facenr = i; + + BLI_addtail(&vd->polyfacemap[*origIndex], e); + } +} + static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *event) { ToolSettings *ts= CTX_data_tool_settings(C); @@ -1635,15 +1726,19 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent VPaint *vp= ts->vpaint; struct VPaintData *vpd; Object *ob= CTX_data_active_object(C); + Scene *scene = CTX_data_scene(C); Mesh *me; float mat[4][4], imat[4][4]; /* context checks could be a poll() */ me= get_mesh(ob); - if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH; + if(me==NULL || me->totpoly==0) + return OPERATOR_PASS_THROUGH; - if(me->mcol==NULL) make_vertexcol(CTX_data_scene(C), 0); - if(me->mcol==NULL) return OPERATOR_CANCELLED; + if(me->mloopcol==NULL) + make_vertexcol(CTX_data_scene(C), 0); + if(me->mloopcol==NULL) + return OPERATOR_CANCELLED; /* make mode data storage */ vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData"); @@ -1653,9 +1748,10 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent vpd->vertexcosnos= mesh_get_mapped_verts_nors(vpd->vc.scene, ob); vpd->indexar= get_indexarray(); vpd->paintcol= vpaint_get_current_col(vp); + vpaint_build_poly_facemap(vpd, me, ob, scene); /* for filtering */ - copy_vpaint_prev(vp, (unsigned int *)me->mcol, me->totface); + copy_vpaint_prev(vp, (unsigned int *)me->mloopcol, me->totloop); /* some old cruft to sort out later */ Mat4MulMat4(mat, ob->obmat, vpd->vc.rv3d->viewmat); @@ -1705,6 +1801,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P Brush *brush = paint_brush(&vp->paint); ViewContext *vc= &vpd->vc; Object *ob= vc->obact; + polyfacemap_e *e; Mesh *me= ob->data; float mat[4][4]; int *indexar= vpd->indexar; @@ -1726,7 +1823,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P /* which faces are involved */ if(vp->flag & VP_AREA) { - totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush->size); + totindex= sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush->size); } else { indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]); @@ -1736,19 +1833,111 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P Mat4SwapMat4(vc->rv3d->persmat, mat); - for(index=0; index<totindex; index++) { - if(indexar[index] && indexar[index]<=me->totface) - vpaint_paint_face(vp, vpd, ob, indexar[index]-1, mval); + if(vp->flag & VP_COLINDEX) { + for(index=0; index<totindex; index++) { + if(indexar[index] && indexar[index]<=me->totpoly) { + MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1); + + if(mpoly->mat_nr!=ob->actcol-1) { + indexar[index]= 0; + } + } + } } + if((G.f & G_FACESELECT) && me->mface) { + for(index=0; index<totindex; index++) { + if(indexar[index] && indexar[index]<=me->totpoly) { + MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1); + if((mpoly->flag & ME_FACE_SEL)==0) + indexar[index]= 0; + } + } + } + Mat4SwapMat4(vc->rv3d->persmat, mat); /* was disabled because it is slow, but necessary for blur */ if(vp->mode == VP_BLUR) do_shared_vertexcol(me); - ED_region_tag_redraw(vc->ar); + for(index=0; index<totindex; index++) { + + if(indexar[index] && indexar[index]<=me->totpoly) { + MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1); + MFace *mf; + MCol *mc; + MLoop *ml; + MLoopCol *mlc; + unsigned int *lcol = ((unsigned int*)me->mloopcol) + mpoly->loopstart; + unsigned int *lcolorig = ((unsigned int*)vp->vpaint_prev) + mpoly->loopstart; + int i, j, alpha; + + if(vp->mode==VP_BLUR) { + unsigned int blend[5] = {0}; + char *col; + + for (j=0; j<mpoly->totloop; j += 2) { + col = (char*)(lcol + j); + blend[0] += col[0]; + blend[1] += col[1]; + blend[2] += col[2]; + blend[3] += col[3]; + } + + blend[0] /= mpoly->totloop; + blend[1] /= mpoly->totloop; + blend[2] /= mpoly->totloop; + blend[3] /= mpoly->totloop; + col = (char*)(blend + 4); + col[0] = blend[0]; + col[1] = blend[1]; + col[2] = blend[2]; + col[3] = blend[3]; + + vpd->paintcol = *((unsigned int*)col); + } + + ml = me->mloop + mpoly->loopstart; + for (i=0; i<mpoly->totloop; i++, ml++) { + alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*ml->v, mval); + if(alpha) vpaint_blend(vp, lcol+i, lcolorig+i, vpd->paintcol, alpha); + } + + #ifdef CPYCOL + #undef CPYCOL + #endif + #define CPYCOL(c, l) (c)->a = (l)->a, (c)->r = (l)->r, (c)->g = (l)->g, (c)->b = (l)->b + + /*update vertex colors for tesselations incrementally, + rather then regenerating the tesselation altogether.*/ + for (e=vpd->polyfacemap[(indexar[index]-1)].first; e; e=e->next) { + mf = me->mface + e->facenr; + mc = me->mcol + e->facenr*4; + + ml = me->mloop + mpoly->loopstart; + mlc = me->mloopcol + mpoly->loopstart; + for (j=0; j<mpoly->totloop; j++, ml++, mlc++) { + if (ml->v == mf->v1) + CPYCOL(mc, mlc); + else if (ml->v == mf->v2) + CPYCOL(mc+1, mlc); + else if (ml->v == mf->v3) + CPYCOL(mc+2, mlc); + else if (mf->v4 && ml->v == mf->v4) + CPYCOL(mc+3, mlc); + + } + } + #undef CPYCOL + } + } + + Mat4SwapMat4(vc->rv3d->persmat, mat); + do_shared_vertexcol(me); + + ED_region_tag_redraw(vc->ar); DAG_id_flush_update(ob->data, OB_RECALC_DATA); } @@ -1763,7 +1952,8 @@ static void vpaint_stroke_done(bContext *C, struct PaintStroke *stroke) /* frees prev buffer */ copy_vpaint_prev(ts->vpaint, NULL, 0); - + BLI_memarena_free(vpd->arena); + MEM_freeN(vpd); } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 4f667ab7976..ca9656250c8 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1138,10 +1138,10 @@ static void sculpt_update_mesh_elements(bContext *C) if((ss->multires = sculpt_multires_active(ob))) { //DerivedMesh *dm = mesh_get_derived_final(CTX_data_scene(C), ob, CD_MASK_BAREMESH); ss->totvert = dm->getNumVerts(dm); - ss->totface = dm->getNumFaces(dm); + ss->totface = dm->getNumTessFaces(dm); ss->mvert = dm->getVertDataArray(dm, CD_MVERT); - ss->mface = dm->getFaceDataArray(dm, CD_MFACE); - ss->face_normals = dm->getFaceDataArray(dm, CD_NORMAL); + ss->mface = dm->getTessFaceDataArray(dm, CD_MFACE); + ss->face_normals = dm->getTessFaceDataArray(dm, CD_NORMAL); } else { Mesh *me = get_mesh(ob); diff --git a/source/blender/editors/space_buttons/SConscript b/source/blender/editors/space_buttons/SConscript index a0a7dad4077..71530d6f92d 100644 --- a/source/blender/editors/space_buttons/SConscript +++ b/source/blender/editors/space_buttons/SConscript @@ -5,7 +5,7 @@ sources = env.Glob('*.c') incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' -incs += ' ../../makesrna ../../render/extern/include' +incs += ' ../../makesrna ../../render/extern/include ../../bmesh' defs = [] diff --git a/source/blender/editors/space_image/Makefile b/source/blender/editors/space_image/Makefile index af15b1d9724..a55b4e58dfa 100644 --- a/source/blender/editors/space_image/Makefile +++ b/source/blender/editors/space_image/Makefile @@ -47,6 +47,7 @@ CPPFLAGS += -I../../makesrna CPPFLAGS += -I../../imbuf CPPFLAGS += -I../../python CPPFLAGS += -I../../render/extern/include +CPPFLAGS += -I../../bmesh CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include # own include diff --git a/source/blender/editors/space_image/SConscript b/source/blender/editors/space_image/SConscript index 874549e6949..2b1d5589cb3 100644 --- a/source/blender/editors/space_image/SConscript +++ b/source/blender/editors/space_image/SConscript @@ -5,7 +5,7 @@ sources = env.Glob('*.c') incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' -incs += ' ../../render/extern/include ../../makesrna' +incs += ' ../../render/extern/include ../../makesrna ../../bmesh' defs = [] diff --git a/source/blender/editors/space_image/image_header.c b/source/blender/editors/space_image/image_header.c index e0fd652bf92..3e15ae1f1f5 100644 --- a/source/blender/editors/space_image/image_header.c +++ b/source/blender/editors/space_image/image_header.c @@ -48,6 +48,7 @@ #include "BKE_mesh.h" #include "BKE_screen.h" #include "BKE_utildefines.h" +#include "BKE_mesh.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index e64bb1a4209..9a4bab03534 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -50,6 +50,7 @@ #include "BKE_mesh.h" #include "BKE_screen.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -257,13 +258,13 @@ static void image_refresh(const bContext *C, ScrArea *sa) if(ima && (ima->source==IMA_SRC_VIEWER || sima->pin)); else if(obedit && obedit->type == OB_MESH) { Mesh *me= (Mesh*)obedit->data; - EditMesh *em= BKE_mesh_get_editmesh(me); - MTFace *tf; + BMEditMesh *em= me->edit_btmesh; + MTexPoly *tf; - if(em && EM_texFaceCheck(em)) { + if(em && EDBM_texFaceCheck(em)) { sima->image= ima= NULL; - tf = EM_get_active_mtface(em, NULL, NULL, 1); /* partially selected face is ok */ + tf = EDBM_get_active_mtexpoly(em, NULL, 1); /* partially selected face is ok */ if(tf && (tf->mode & TF_TEX)) { /* don't need to check for pin here, see above */ @@ -273,8 +274,6 @@ static void image_refresh(const bContext *C, ScrArea *sa) else sima->curtile= tf->tile; } } - - BKE_mesh_end_editmesh(obedit->data, em); } } @@ -765,13 +764,9 @@ int ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit) return 0; if(obedit && obedit->type == OB_MESH) { - EditMesh *em = BKE_mesh_get_editmesh(obedit->data); - int ret; - - ret = EM_texFaceCheck(em); + BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh; - BKE_mesh_end_editmesh(obedit->data, em); - return ret; + return EDBM_texFaceCheck(em); } return 0; @@ -784,13 +779,9 @@ int ED_space_image_show_uvshadow(SpaceImage *sima, Object *obedit) if(ED_space_image_show_paint(sima)) if(obedit && obedit->type == OB_MESH) { - EditMesh *em = BKE_mesh_get_editmesh(obedit->data); - int ret; - - ret = EM_texFaceCheck(em); + BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh; - BKE_mesh_end_editmesh(obedit->data, em); - return ret; + return EDBM_texFaceCheck(em); } return 0; diff --git a/source/blender/editors/space_info/Makefile b/source/blender/editors/space_info/Makefile index 931c2f2097c..99ab1d2c514 100644 --- a/source/blender/editors/space_info/Makefile +++ b/source/blender/editors/space_info/Makefile @@ -47,6 +47,7 @@ CPPFLAGS += -I../../makesdna CPPFLAGS += -I../../makesrna CPPFLAGS += -I../../imbuf CPPFLAGS += -I../../python +CPPFLAGS += -I../../bmesh CPPFLAGS += -I../../blenfont CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include diff --git a/source/blender/editors/space_info/SConscript b/source/blender/editors/space_info/SConscript index 01268115687..ba1110274ff 100644 --- a/source/blender/editors/space_info/SConscript +++ b/source/blender/editors/space_info/SConscript @@ -4,7 +4,7 @@ Import ('env') sources = env.Glob('*.c') incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf ../../blenfont' -incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' +incs += ' ../../bmesh ../../windowmanager #/intern/guardedalloc #/extern/glew/include' defs = [] diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 60cac0a00fa..9261a2a5d8d 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -46,6 +46,7 @@ #include "BKE_mesh.h" #include "BKE_particle.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "ED_armature.h" #include "ED_mesh.h" @@ -138,26 +139,16 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats) static void stats_object_edit(Object *obedit, SceneStats *stats) { if(obedit->type==OB_MESH) { - /* Mesh Edit */ - EditMesh *em= BKE_mesh_get_editmesh(obedit->data); - EditVert *eve; - EditEdge *eed; - EditFace *efa; + BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh; + + stats->totvert = em->bm->totvert; + stats->totvertsel = em->bm->totvertsel; - for(eve= em->verts.first; eve; eve=eve->next) { - stats->totvert++; - if(eve->f & SELECT) stats->totvertsel++; - } - for(eed= em->edges.first; eed; eed=eed->next) { - stats->totedge++; - if(eed->f & SELECT) stats->totedgesel++; - } - for(efa= em->faces.first; efa; efa=efa->next) { - stats->totface++; - if(efa->f & SELECT) stats->totfacesel++; - } + stats->totedge = em->bm->totedge; + stats->totedgesel = em->bm->totedgesel; - EM_validate_selections(em); + stats->totface = em->bm->totface; + stats->totfacesel = em->bm->totfacesel; } else if(obedit->type==OB_ARMATURE){ /* Armature Edit */ diff --git a/source/blender/editors/space_node/SConscript b/source/blender/editors/space_node/SConscript index fd0dfe83852..5493e2d739f 100644 --- a/source/blender/editors/space_node/SConscript +++ b/source/blender/editors/space_node/SConscript @@ -14,7 +14,7 @@ if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): if env['CC'] == 'gcc': #cf.append('-Werror') pass - + if env['OURPLATFORM'] == 'linux2': cflags='-pthread' incs += ' ../../../extern/binreloc/include' diff --git a/source/blender/editors/space_view3d/SConscript b/source/blender/editors/space_view3d/SConscript index 057c98a1d49..84420da9076 100644 --- a/source/blender/editors/space_view3d/SConscript +++ b/source/blender/editors/space_view3d/SConscript @@ -7,7 +7,7 @@ defs = [] incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../render/extern/include #/intern/guardedalloc' -incs += ' ../../gpu ../../makesrna ../../blenfont' +incs += ' ../../gpu ../../makesrna ../../blenfont ../../bmesh' incs += ' #/intern/smoke/extern' incs += ' #source/kernel/gen_system' diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index 365b9ff03f7..0d8e1381756 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -63,6 +63,7 @@ #include "BKE_paint.h" #include "BKE_property.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -399,7 +400,7 @@ static void draw_textured_end() glPopMatrix(); } -static int draw_tface__set_draw_legacy(MTFace *tface, MCol *mcol, int matnr) +static int draw_tface__set_draw_legacy(MTFace *tface, int has_vcol, int matnr) { if (tface && (tface->mode&TF_INVISIBLE)) return 0; @@ -409,7 +410,7 @@ static int draw_tface__set_draw_legacy(MTFace *tface, MCol *mcol, int matnr) } else if (tface && tface->mode&TF_OBCOL) { glColor3ubv(Gtexdraw.obcol); return 2; /* Don't set color */ - } else if (!mcol) { + } else if (!has_vcol) { if (tface) glColor3f(1.0, 1.0, 1.0); else { Material *ma= give_current_material(Gtexdraw.ob, matnr+1); @@ -438,15 +439,15 @@ static int draw_tface__set_draw(MTFace *tface, MCol *mcol, int matnr) static void add_tface_color_layer(DerivedMesh *dm) { MTFace *tface = DM_get_face_data_layer(dm, CD_MTFACE); - MFace *mface = DM_get_face_data_layer(dm, CD_MFACE); + MFace *mface = dm->getTessFaceArray(dm); MCol *finalCol; int i,j; - MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL); + MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL); if(!mcol) - mcol = dm->getFaceDataArray(dm, CD_MCOL); + mcol = dm->getTessFaceDataArray(dm, CD_MCOL); - finalCol = MEM_mallocN(sizeof(MCol)*4*dm->getNumFaces(dm),"add_tface_color_layer"); - for(i=0;i<dm->getNumFaces(dm);i++) { + finalCol = MEM_mallocN(sizeof(MCol)*4*dm->getNumTessFaces(dm),"add_tface_color_layer"); + for(i=0;i<dm->getNumTessFaces(dm);i++) { if (tface && (tface->mode&TF_INVISIBLE)) { if( mcol ) memcpy(&finalCol[i*4],&mcol[i*4],sizeof(MCol)*4); @@ -506,30 +507,53 @@ static void add_tface_color_layer(DerivedMesh *dm) static int draw_tface_mapped__set_draw(void *userData, int index) { Mesh *me = (Mesh*)userData; - MTFace *tface = (me->mtface)? &me->mtface[index]: NULL; - MFace *mface = (me->mface)? &me->mface[index]: NULL; - MCol *mcol = (me->mcol)? &me->mcol[index]: NULL; - int matnr = me->mface[index].mat_nr; - if (mface && mface->flag&ME_HIDE) return 0; - return draw_tface__set_draw(tface, mcol, matnr); + MTexPoly *tpoly = (me->mtpoly)? &me->mtpoly[index]: NULL; + MPoly *mpoly = (me->mpoly)? &me->mpoly[index]: NULL; + MTFace mtf; + int matnr = me->mpoly[index].mat_nr; + + if (mpoly && mpoly->flag&ME_HIDE) return 0; + + memset(&mtf, 0, sizeof(mtf)); + if (tpoly) { + mtf.flag = tpoly->flag; + mtf.tpage = tpoly->tpage; + mtf.transp = tpoly->transp; + mtf.mode = tpoly->mode; + mtf.tile = tpoly->tile; + mtf.unwrap = tpoly->unwrap; + } + + return draw_tface__set_draw(&mtf, CustomData_has_layer(&me->ldata, CD_MLOOPCOL), matnr); } static int draw_em_tf_mapped__set_draw(void *userData, int index) { - EditMesh *em = userData; - EditFace *efa= EM_get_face_for_index(index); - MTFace *tface; - MCol *mcol; - int matnr; + BMEditMesh *em = userData; + BMFace *efa= EDBM_get_face_for_index(em, index); + MTexPoly *tpoly; + MTFace mtf; + int matnr, has_vcol; - if (efa==NULL || efa->h) + if (efa==NULL || BM_TestHFlag(efa, BM_HIDDEN)) return 0; - tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); + tpoly = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + has_vcol = CustomData_has_layer(&em->bm->ldata, CD_MLOOPCOL); matnr = efa->mat_nr; - return draw_tface__set_draw(tface, mcol, matnr); + memset(&mtf, 0, sizeof(mtf)); + + if (tpoly) { + mtf.flag = tpoly->flag; + mtf.tpage = tpoly->tpage; + mtf.transp = tpoly->transp; + mtf.mode = tpoly->mode; + mtf.tile = tpoly->tile; + mtf.unwrap = tpoly->unwrap; + } + + return draw_tface__set_draw(&mtf, has_vcol, matnr); } static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r) @@ -643,7 +667,7 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *o if(ob->mode & OB_MODE_EDIT) { glColor4f(1.0f,1.0f,1.0f,1.0f); - dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, me->edit_mesh); + dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, me->edit_btmesh); } else if(faceselect) { if(ob->mode & OB_MODE_WEIGHT_PAINT) dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 78dd53e7271..dfbdce14992 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -94,6 +94,8 @@ #include "BKE_smoke.h" #include "BKE_unit.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" + #include "smoke_API.h" #include "BIF_gl.h" @@ -232,7 +234,7 @@ static int check_material_alpha(Base *base, Mesh *me, int glsl) if(G.f & G_PICKSEL) return 0; - if(me->edit_mesh) + if(me->edit_btmesh) return 0; return (glsl || (base->object->dtx & OB_DRAWTRANSP)); @@ -1307,16 +1309,21 @@ static void drawlattice(Scene *scene, View3D *v3d, Object *ob) * use the object matrix in the useual way */ static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s) { - struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData; - EditVert *eve = EM_get_vert_for_index(index); + struct { void (*func)(void *userData, BMVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData; + BMVert *eve = EDBM_get_vert_for_index(data->vc.em, index); - if (eve->h==0) { + if (!BM_TestHFlag(eve, BM_HIDDEN)) { short s[2]= {IS_CLIPPED, 0}; + float co2[3]; + + VECCOPY(co2, co); + + Mat4MulVecfl(data->vc.obedit->obmat, co2); if (data->clipVerts) { - view3d_project_short_clip(data->vc.ar, co, s); + project_short(data->vc.ar, co2, s); } else { - view3d_project_short_noclip(data->vc.ar, co, s); + project_short_noclip(data->vc.ar, co2, s); } if (s[0]!=IS_CLIPPED) @@ -1324,36 +1331,43 @@ static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co } } -void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts) +void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BMVert *eve, int x, int y, int index), void *userData, int clipVerts) { - struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data; - DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); + struct { void (*func)(void *userData, BMVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } data; + DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); data.vc= *vc; data.func = func; data.userData = userData; data.clipVerts = clipVerts; - EM_init_index_arrays(vc->em, 1, 0, 0); + EDBM_init_index_arrays(vc->em, 1, 0, 0); dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data); - EM_free_index_arrays(); + EDBM_free_index_arrays(vc->em); dm->release(dm); } static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co) { - struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData; - EditEdge *eed = EM_get_edge_for_index(index); + struct { void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData; + BMEdge *eed = EDBM_get_edge_for_index(data->vc.em, index); short s[2][2]; + float v1_co[3], v2_co[3]; + + VECCOPY(v1_co, v0co); + VECCOPY(v2_co, v1co); - if (eed->h==0) { + Mat4MulVecfl(data->vc.obedit->obmat, v1_co); + Mat4MulVecfl(data->vc.obedit->obmat, v2_co); + + if (!BM_TestHFlag(eed, BM_HIDDEN)) { if (data->clipVerts==1) { - view3d_project_short_clip(data->vc.ar, v0co, s[0]); - view3d_project_short_clip(data->vc.ar, v1co, s[1]); + project_short(data->vc.ar, v1_co, s[0]); + project_short(data->vc.ar, v2_co, s[1]); } else { - view3d_project_short_noclip(data->vc.ar, v0co, s[0]); - view3d_project_short_noclip(data->vc.ar, v1co, s[1]); + project_short_noclip(data->vc.ar, v1_co, s[0]); + project_short_noclip(data->vc.ar, v2_co, s[1]); if (data->clipVerts==2) { if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy)) @@ -1366,48 +1380,51 @@ static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0 } } -void mesh_foreachScreenEdge(ViewContext *vc, void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts) +void mesh_foreachScreenEdge(ViewContext *vc, void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts) { - struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data; - DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); + struct { void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } data; + DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); data.vc= *vc; data.func = func; data.userData = userData; data.clipVerts = clipVerts; - EM_init_index_arrays(vc->em, 0, 1, 0); + EDBM_init_index_arrays(vc->em, 0, 1, 0); dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data); - EM_free_index_arrays(); + EDBM_free_index_arrays(vc->em); dm->release(dm); } static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no) { - struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData; - EditFace *efa = EM_get_face_for_index(index); + struct { void (*func)(void *userData, BMFace *efa, int x, int y, int index); void *userData; ViewContext vc; float pmat[4][4], vmat[4][4]; } *data = userData; + float cent2[3]; + BMFace *efa = EDBM_get_face_for_index(data->vc.em, index); short s[2]; - if (efa && efa->h==0 && efa->fgonf!=EM_FGON) { - view3d_project_short_clip(data->vc.ar, cent, s); + VECCOPY(cent2, cent); + if (efa && !BM_TestHFlag(efa, BM_HIDDEN)) { + Mat4MulVecfl(data->vc.obedit->obmat, cent2); + project_short(data->vc.ar, cent2, s); data->func(data->userData, efa, s[0], s[1], index); } } -void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData) +void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, BMFace *efa, int x, int y, int index), void *userData) { - struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data; - DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); + struct { void (*func)(void *userData, BMFace *efa, int x, int y, int index); void *userData; ViewContext vc; float pmat[4][4], vmat[4][4]; } data; + DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); data.vc= *vc; data.func = func; data.userData = userData; - EM_init_index_arrays(vc->em, 0, 0, 1); + EDBM_init_index_arrays(vc->em, 0, 0, 1); dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data); - EM_free_index_arrays(); + EDBM_free_index_arrays(vc->em); dm->release(dm); } @@ -1471,46 +1488,54 @@ void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no) { - ToolSettings *ts= ((Scene *)userData)->toolsettings; - EditFace *efa = EM_get_face_for_index(index); + Scene *scene= ((void **)userData)[0]; + BMEditMesh *em = ((void **)userData)[1]; + BMFace *efa = EDBM_get_face_for_index(em, index); + ToolSettings *ts= scene->toolsettings; - if (efa->h==0 && efa->fgonf!=EM_FGON) { + if (!BM_TestHFlag(efa, BM_HIDDEN)) { glVertex3fv(cent); glVertex3f( cent[0] + no[0]*ts->normalsize, cent[1] + no[1]*ts->normalsize, cent[2] + no[2]*ts->normalsize); } } -static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) +static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm) { + void *ptrs[2] = {scene, em}; + glBegin(GL_LINES); - dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene); + dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, ptrs); glEnd(); } static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *no) { - EditFace *efa = EM_get_face_for_index(index); - int sel = *((int*) userData); + BMFace *efa = EDBM_get_face_for_index(((void **)userData)[0], index); + BMEditMesh *em = ((void **)userData)[0]; + int sel = *(((int **)userData)[1]); - if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) { + if (!BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT)==sel) { bglVertex3fv(cent); } } -static void draw_dm_face_centers(DerivedMesh *dm, int sel) +static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, int sel) { + void *ptrs[2] = {em, &sel}; + bglBegin(GL_POINTS); - dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel); + dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, ptrs); bglEnd(); } static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s) { - Scene *scene= (Scene *)userData; + Scene *scene= ((void **)userData)[0]; ToolSettings *ts= scene->toolsettings; - EditVert *eve = EM_get_vert_for_index(index); + BMEditMesh *em = ((void **)userData)[1]; + BMVert *eve = EDBM_get_vert_for_index(em, index); - if (eve->h==0) { + if (!BM_TestHFlag(eve, BM_HIDDEN)) { glVertex3fv(co); if (no_f) { @@ -1524,20 +1549,78 @@ static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, } } } -static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) +static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm) { + void *ptrs[2] = {scene, em}; + glBegin(GL_LINES); - dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene); + dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, ptrs); + glEnd(); +} + +/* check if all verts of the face are pinned */ +static int check_pinned_face(BMesh *bm, BMFace *efa) +{ + BMIter vfiter; + BMVert *v; + int vcount = 0; + + BM_ITER(v, &vfiter, bm, BM_VERTS_OF_FACE, efa) { + if(BM_TestHFlag(v, BM_PINNED)) vcount ++; + } + + if( vcount == efa->len) return 1; + return 0; +} + +static void draw_dm_vert_pins__mapFunc(void *userData, int index, float *co) +{ + struct {BMEditMesh *em; Mesh *me;} *data = userData; + BMVert *eve = EDBM_get_vert_for_index(data->em, index); + BMFace *fv; + BMIter fviter; + float vsize = UI_GetThemeValuef(TH_VERTEX_SIZE); + int small=0; + + if (!BM_TestHFlag(eve, BM_HIDDEN)) { + if (BM_TestHFlag(eve, BM_PINNED)) { + BM_ITER(fv, &fviter, data->em->bm, BM_FACES_OF_VERT, eve) { + small += check_pinned_face(data->em->bm, fv); + } + if(small == 0) { + bglEnd(); + glPointSize(vsize*1.5); + glBegin(GL_POINTS); + glVertex3fv(co); + } + else { + bglEnd(); + glPointSize(vsize*0.5); + glBegin(GL_POINTS); + glVertex3fv(co); + } + } + } +} + +static void draw_dm_vert_pins(BMEditMesh *em, DerivedMesh *dm, Mesh *me) +{ + struct { BMEditMesh *em; Mesh *me;} data; + + data.em = em; + data.me = me; + + dm->foreachMappedVert(dm, draw_dm_vert_pins__mapFunc, &data); glEnd(); } /* Draw verts with color set based on selection */ static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s) { - struct { int sel; EditVert *eve_act; } * data = userData; - EditVert *eve = EM_get_vert_for_index(index); + struct { BMEditMesh *em; int sel; BMVert *eve_act; } *data = userData; + BMVert *eve = EDBM_get_vert_for_index(data->em, index); - if (eve->h==0 && (eve->f&SELECT)==data->sel) { + if (!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT)==data->sel) { /* draw active larger - need to stop/start point drawing for this :/ */ if (eve==data->eve_act) { float size = UI_GetThemeValuef(TH_VERTEX_SIZE); @@ -1575,13 +1658,18 @@ typedef struct { } EditMeshDerivedMesh; #endif -static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act) +static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, int sel, BMVert *eve_act) { - struct { int sel; EditVert *eve_act; } data; + struct { BMEditMesh *em; int sel; BMVert *eve_act; } data; //GPUBuffer *buffer; //float *varray; data.sel = sel; data.eve_act = eve_act; + data.em = em; + + bglBegin(GL_POINTS); + dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data); + bglEnd(); #if 0 /* first come the unselected vertices, then the selected */ @@ -1640,16 +1728,18 @@ static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act) /* Draw edges with color set based on selection */ static int draw_dm_edges_sel__setDrawOptions(void *userData, int index) { - EditEdge *eed = EM_get_edge_for_index(index); + BMEdge *eed; //unsigned char **cols = userData, *col; - struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData; + struct { BMEditMesh *em; unsigned char *baseCol, *selCol, *actCol; BMEdge *eed_act; } * data = userData; unsigned char *col; - if (eed->h==0) { + eed = EDBM_get_edge_for_index(data->em, index); + + if (!BM_TestHFlag(eed, BM_HIDDEN)) { if (eed==data->eed_act) { glColor4ubv(data->actCol); } else { - if (eed->f&SELECT) { + if (BM_TestHFlag(eed, BM_SELECT)) { col = data->selCol; } else { col = data->baseCol; @@ -1664,13 +1754,15 @@ static int draw_dm_edges_sel__setDrawOptions(void *userData, int index) return 0; } } -static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) +static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, + unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act) { - struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data; + struct { BMEditMesh *em; unsigned char *baseCol, *selCol, *actCol; BMEdge *eed_act; } data; data.baseCol = baseCol; data.selCol = selCol; data.actCol = actCol; + data.em = em; data.eed_act = eed_act; dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data); } @@ -1678,24 +1770,24 @@ static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned /* Draw edges */ static int draw_dm_edges__setDrawOptions(void *userData, int index) { - return EM_get_edge_for_index(index)->h==0; + return !BM_TestHFlag(EDBM_get_edge_for_index(userData, index), BM_HIDDEN); } -static void draw_dm_edges(DerivedMesh *dm) +static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm) { - dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL); + dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em); } /* Draw edges with color interpolated based on selection */ static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index) { - return EM_get_edge_for_index(index)->h==0; + return !BM_TestHFlag(EDBM_get_edge_for_index(((void**)userData)[0], index), BM_HIDDEN); } static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t) { - EditEdge *eed = EM_get_edge_for_index(index); + BMEdge *eed = EDBM_get_edge_for_index(((void**)userData)[0], index); unsigned char **cols = userData; - unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0]; - unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0]; + unsigned char *col0 = cols[(BM_TestHFlag(eed->v1, BM_SELECT))?2:1]; + unsigned char *col1 = cols[(BM_TestHFlag(eed->v2, BM_SELECT))?2:1]; glColor4ub( col0[0] + (col1[0]-col0[0])*t, col0[1] + (col1[1]-col0[1])*t, @@ -1703,9 +1795,9 @@ static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int i col0[3] + (col1[3]-col0[3])*t); } -static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol) +static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol) { - unsigned char *cols[2] = {baseCol, selCol}; + unsigned char *cols[3] = {em, baseCol, selCol}; #if 0 int elemsize = sizeof(float)*3+sizeof(unsigned char)*4; EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm; @@ -1760,25 +1852,75 @@ static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, un /* Draw only seam edges */ static int draw_dm_edges_seams__setDrawOptions(void *userData, int index) { - EditEdge *eed = EM_get_edge_for_index(index); + BMEdge *eed = EDBM_get_edge_for_index(userData, index); + + return !BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SEAM); +} + +static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm) +{ + dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em); +} + +/* Draw only pinned edges */ +static int draw_dm_edges_pins__setDrawOptions(void *userData, int index) +{ + struct {BMEditMesh *em; Mesh *me;} *data = userData; + + BMEdge *eed = EDBM_get_edge_for_index(data->em, index); + BMIter feiter; + BMFace *fe; + + int fcount, fpcount = 0; + int pin = 0; + + /* If pinned faces are drawn then only draw pinned edges at the borders. + This looks way better and the user still has all the info he needs. */ + if(data->me->drawflag & ME_DRAW_PINS) { + if( BM_TestHFlag(eed->v1, BM_PINNED) && BM_TestHFlag(eed->v2, BM_PINNED) ) { + pin = 1; - return (eed->h==0 && eed->seam); + fcount = 0; + BM_ITER(fe, &feiter, data->em->bm, BM_FACES_OF_EDGE, eed) { + fcount ++; + fpcount += check_pinned_face(data->em->bm, fe); + } + } + } + else { + pin = BM_TestHFlag(eed->v1, BM_PINNED) && BM_TestHFlag(eed->v2, BM_PINNED); + } + + if( !BM_TestHFlag(eed, BM_HIDDEN)) { + /* Edges with at least one adherent pinned face are considered borders. + If there are more than two adherent faces overall of which at least two are pinned it's also consideres a border. */ + if( fpcount == 2 && fcount <= 2) { + return 0; } + else { + return pin; } + } } -static void draw_dm_edges_seams(DerivedMesh *dm) + +static void draw_dm_edges_pins(BMEditMesh *em, DerivedMesh *dm, Mesh *me) { - dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL); + struct { BMEditMesh *em; Mesh *me;} data; + + data.em = em; + data.me = me; + + dm->drawMappedEdges(dm, draw_dm_edges_pins__setDrawOptions, &data); } /* Draw only sharp edges */ static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index) { - EditEdge *eed = EM_get_edge_for_index(index); + BMEdge *eed = EDBM_get_edge_for_index(userData, index); - return (eed->h==0 && eed->sharp); + return !BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SHARP); } -static void draw_dm_edges_sharp(DerivedMesh *dm) +static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm) { - dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL); + dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em); } @@ -1786,18 +1928,35 @@ static void draw_dm_edges_sharp(DerivedMesh *dm) * return 2 for the active face so it renders with stipple enabled */ static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r) { - struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData; - EditFace *efa = EM_get_face_for_index(index); + struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} *data = userData; + BMFace *efa = EDBM_get_face_for_index(data->em, index); unsigned char *col; + BMIter vfiter; + BMVert *v; + int vcount, pin=0; + int opac = UI_GetThemeValue(TH_PIN_OPAC); - if (efa->h==0) { + if (!BM_TestHFlag(efa, BM_HIDDEN)) { + + /* Check if all verts of a face are pinned. If so, then display it in a darker shade. */ + if(data->me->drawflag & ME_DRAW_PINS) + pin = check_pinned_face(data->em->bm, efa); + if (efa == data->efa_act) { - glColor4ubv(data->cols[2]); + if(pin==0) { glColor4ubv(data->cols[2]); } + else { + col = data->cols[2]; + glColor4ub(col[0]-col[0]*0.9, col[1]-col[1]*0.9, col[2]-col[2]*0.9, opac*2.55); + } + return 2; /* stipple */ } else { - col = data->cols[(efa->f&SELECT)?1:0]; + col = data->cols[BM_TestHFlag(efa, BM_SELECT)?1:0]; if (col[3]==0) return 0; - glColor4ubv(col); + + if(pin==0) { glColor4ubv(col); } + else { glColor4ub(col[0]-col[0]*0.9, col[1]-col[1]*0.9, col[2]-col[2]*0.9, opac*2.55); } + return 1; } } @@ -1805,11 +1964,13 @@ static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *dra } /* also draws the active face */ -static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) +static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, + unsigned char *selCol, unsigned char *actCol, BMFace *efa_act, Mesh *me) { - struct { unsigned char *cols[3]; EditFace *efa_act; } data; + struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} data; + //EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm; - EditFace *efa; + BMFace *efa; unsigned char *col; GPUBuffer *buffer; unsigned char *varray; @@ -1817,11 +1978,13 @@ static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned int i, draw=0; int elemsize = (sizeof(float)*6+sizeof(unsigned char)*4); data.cols[0] = baseCol; + data.em = em; data.cols[1] = selCol; data.cols[2] = actCol; data.efa_act = efa_act; + data.me = me; - +#if 0 //BMESH_TODO buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( elemsize*dm->getNumFaces(dm)*3*2, 0 ); if( dm->getVertCos == 0 && (varray = GPU_buffer_lock_stream( buffer )) ) { int prevdraw = 0; @@ -2035,34 +2198,38 @@ static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned } GPU_buffer_unbind(); } else { +#endif dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0); + +#if 0 } GPU_buffer_free( buffer, 0 ); +#endif } static int draw_dm_creases__setDrawOptions(void *userData, int index) { - EditEdge *eed = EM_get_edge_for_index(index); + BMEdge *eed = EDBM_get_edge_for_index(userData, index); - if (eed->h==0 && eed->crease!=0.0) { + if (!BM_TestHFlag(eed, BM_HIDDEN) && eed->crease!=0.0) { UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease); return 1; } else { return 0; } } -static void draw_dm_creases(DerivedMesh *dm) +static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm) { glLineWidth(3.0); - dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL); + dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, em); glLineWidth(1.0); } static int draw_dm_bweights__setDrawOptions(void *userData, int index) { - EditEdge *eed = EM_get_edge_for_index(index); + BMEdge *eed = EDBM_get_edge_for_index(userData, index); - if (eed->h==0 && eed->bweight!=0.0) { + if (!BM_TestHFlag(eed, BM_HIDDEN) && eed->bweight!=0.0) { UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight); return 1; } else { @@ -2071,26 +2238,26 @@ static int draw_dm_bweights__setDrawOptions(void *userData, int index) } static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s) { - EditVert *eve = EM_get_vert_for_index(index); + BMVert *eve = EDBM_get_vert_for_index(userData, index); - if (eve->h==0 && eve->bweight!=0.0) { + if (!BM_TestHFlag(eve, BM_HIDDEN) && eve->bweight!=0.0) { UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight); bglVertex3fv(co); } } -static void draw_dm_bweights(Scene *scene, DerivedMesh *dm) +static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm) { ToolSettings *ts= scene->toolsettings; if (ts->selectmode & SCE_SELECT_VERTEX) { glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2); bglBegin(GL_POINTS); - dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL); + dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, em); bglEnd(); } else { glLineWidth(3.0); - dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL); + dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, em); glLineWidth(1.0); } } @@ -2104,7 +2271,8 @@ static void draw_dm_bweights(Scene *scene, DerivedMesh *dm) /* EditMesh drawing routines*/ -static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act) +static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, + BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act) { ToolSettings *ts= scene->toolsettings; int sel; @@ -2141,13 +2309,13 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditM if(ts->selectmode & SCE_SELECT_VERTEX) { glPointSize(size); glColor4ubv((GLubyte *)col); - draw_dm_verts(cageDM, sel, eve_act); + draw_dm_verts(em, cageDM, sel, eve_act); } if( CHECK_OB_DRAWFACEDOT(scene, v3d, obedit->dt) ) { glPointSize(fsize); glColor4ubv((GLubyte *)fcol); - draw_dm_face_centers(cageDM, sel); + draw_dm_face_centers(em, cageDM, sel); } if (pass==0) { @@ -2161,7 +2329,9 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditM glPointSize(1.0); } -static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act) +static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d, + Mesh *me, DerivedMesh *cageDM, short sel_only, + BMEdge *eed_act) { ToolSettings *ts= scene->toolsettings; int pass; @@ -2194,21 +2364,21 @@ static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh } if(ts->selectmode == SCE_SELECT_FACE) { - draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act); + draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act); } else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) { if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) { glShadeModel(GL_SMOOTH); - draw_dm_edges_sel_interp(cageDM, wireCol, selCol); + draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol); glShadeModel(GL_FLAT); } else { - draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act); + draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act); } } else { if (!sel_only) { glColor4ubv(wireCol); - draw_dm_edges(cageDM); + draw_dm_edges(em, cageDM); } } @@ -2219,8 +2389,10 @@ static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh } } -static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit) +static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, + Object *ob, BMEditMesh *em, UnitSettings *unit) { +#if 0 Mesh *me= ob->data; EditEdge *eed; EditFace *efa; @@ -2392,13 +2564,14 @@ static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, E glEnable(GL_DEPTH_TEST); bglPolygonOffset(rv3d->dist, 0.0f); } +#endif } static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r) { - EditFace *efa = EM_get_face_for_index(index); + BMFace *efa = EDBM_get_face_for_index(userData, index); - if (efa->h==0) { + if (!BM_TestHFlag(efa, BM_HIDDEN)) { GPU_enable_material(efa->mat_nr+1, NULL); return 1; } @@ -2408,31 +2581,33 @@ static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index) { - EditFace *efa = EM_get_face_for_index(index); + BMFace *efa = EDBM_get_face_for_index(userData, index); - return (efa->h==0); + return !BM_TestHFlag(efa, BM_HIDDEN); } -static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt) +static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, + BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt) + { Mesh *me = ob->data; - EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */ - EditEdge *eed_act = NULL; - EditVert *eve_act = NULL; + BMFace *efa_act = EDBM_get_actFace(em, 0); /* annoying but active faces is stored differently */ + BMEdge *eed_act = NULL; + BMVert *eve_act = NULL; - if (em->selected.last) { - EditSelection *ese = em->selected.last; + if (em->bm->selected.last) { + BMEditSelection *ese = em->bm->selected.last; /* face is handeled above */ /*if (ese->type == EDITFACE ) { efa_act = (EditFace *)ese->data; } else */ if ( ese->type == EDITEDGE ) { - eed_act = (EditEdge *)ese->data; + eed_act = (BMEdge *)ese->data; } else if ( ese->type == EDITVERT ) { - eve_act = (EditVert *)ese->data; + eve_act = (BMVert *)ese->data; } } - EM_init_index_arrays(em, 1, 1, 1); + EDBM_init_index_arrays(em, 1, 1, 1); if(dt>OB_WIRE) { if(CHECK_OB_DRAWTEXTURE(v3d, dt)) { @@ -2440,7 +2615,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material, - draw_em_fancy__setGLSLFaceOpts, NULL); + draw_em_fancy__setGLSLFaceOpts, em); GPU_disable_material(); glFrontFace(GL_CCW); @@ -2451,9 +2626,10 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object } else { /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */ - GPUBuffer *buffer = GPU_buffer_legacy(em->derivedFinal)?0:GPU_buffer_alloc( sizeof(float)*6*em->totface*3*2, 0 ); + GPUBuffer *buffer = GPU_buffer_legacy(em->derivedFinal)?0:GPU_buffer_alloc( sizeof(float)*6*em->tottri*3*2, 0 ); float *varray; - EditFace *efa; + BMFace *efa; + BMLoop **ls; int i, curmat = 0, draw = 0; glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED); @@ -2469,9 +2645,14 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object GPU_interleaved_setup( buffer, datatype ); glShadeModel(GL_SMOOTH); varray = GPU_buffer_lock_stream( buffer ); - for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) { - int drawSmooth = (efa->flag & ME_SMOOTH); - if( efa->h == 0 ) { + for (i=0; i<em->tottri; i++) { + int drawSmooth; + + ls = em->looptris[i]; + efa = ls[0]->f; + drawSmooth = BM_TestHFlag(efa, BM_SMOOTH); + + if( !BM_TestHFlag(efa, BM_HIDDEN) ) { curmat = efa->mat_nr+1; draw = 1; } @@ -2494,48 +2675,26 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object } if( draw != 0 ) { if(!drawSmooth) { - VECCOPY(&varray[numfaces*18],efa->v1->co); - VECCOPY(&varray[numfaces*18+3],efa->n); + VECCOPY(&varray[numfaces*18], ls[0]->v->co); + VECCOPY(&varray[numfaces*18+3], efa->no); - VECCOPY(&varray[numfaces*18+6],efa->v2->co); - VECCOPY(&varray[numfaces*18+9],efa->n); + VECCOPY(&varray[numfaces*18+6], ls[1]->v->co); + VECCOPY(&varray[numfaces*18+9], efa->no); - VECCOPY(&varray[numfaces*18+12],efa->v3->co); - VECCOPY(&varray[numfaces*18+15],efa->n); + VECCOPY(&varray[numfaces*18+12], ls[2]->v->co); + VECCOPY(&varray[numfaces*18+15], efa->no); numfaces++; - if( efa->v4 ) { - VECCOPY(&varray[numfaces*18],efa->v3->co); - VECCOPY(&varray[numfaces*18+3],efa->n); - - VECCOPY(&varray[numfaces*18+6],efa->v4->co); - VECCOPY(&varray[numfaces*18+9],efa->n); - - VECCOPY(&varray[numfaces*18+12],efa->v1->co); - VECCOPY(&varray[numfaces*18+15],efa->n); - numfaces++; - } } else { - VECCOPY(&varray[numfaces*18],efa->v1->co); - VECCOPY(&varray[numfaces*18+3],efa->v1->no); + VECCOPY(&varray[numfaces*18],ls[0]->v->co); + VECCOPY(&varray[numfaces*18+3],ls[0]->v->no); - VECCOPY(&varray[numfaces*18+6],efa->v2->co); - VECCOPY(&varray[numfaces*18+9],efa->v2->no); + VECCOPY(&varray[numfaces*18+6],ls[1]->v->co); + VECCOPY(&varray[numfaces*18+9],ls[1]->v->no); - VECCOPY(&varray[numfaces*18+12],efa->v3->co); - VECCOPY(&varray[numfaces*18+15],efa->v3->no); + VECCOPY(&varray[numfaces*18+12],ls[2]->v->co); + VECCOPY(&varray[numfaces*18+15],ls[2]->v->no); numfaces++; - if( efa->v4 ) { - VECCOPY(&varray[numfaces*18],efa->v3->co); - VECCOPY(&varray[numfaces*18+3],efa->v3->no); - - VECCOPY(&varray[numfaces*18+6],efa->v4->co); - VECCOPY(&varray[numfaces*18+9],efa->v4->no); - - VECCOPY(&varray[numfaces*18+12],efa->v1->co); - VECCOPY(&varray[numfaces*18+15],efa->v1->no); - numfaces++; - } } } prevdraw = draw; @@ -2592,7 +2751,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object if CHECK_OB_DRAWTEXTURE(v3d, dt) col1[3] = 0; - draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act); + draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act, me); glDisable(GL_BLEND); glDepthMask(1); // restore write in zbuffer @@ -2607,7 +2766,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object glEnable(GL_BLEND); glDepthMask(0); // disable write in zbuffer, needed for nice transp - draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act); + draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act, me); glDisable(GL_BLEND); glDepthMask(1); // restore write in zbuffer @@ -2619,14 +2778,14 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */ /* only draw selected edges otherwise there is no way of telling if a face is selected */ - draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act); + draw_em_fancy_edges(em, scene, v3d, me, cageDM, 1, eed_act); } else { if(me->drawflag & ME_DRAWSEAMS) { UI_ThemeColor(TH_EDGE_SEAM); glLineWidth(2); - draw_dm_edges_seams(cageDM); + draw_dm_edges_seams(em, cageDM); glColor3ub(0,0,0); glLineWidth(1); @@ -2636,20 +2795,30 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object UI_ThemeColor(TH_EDGE_SHARP); glLineWidth(2); - draw_dm_edges_sharp(cageDM); + draw_dm_edges_sharp(em, cageDM); glColor3ub(0,0,0); glLineWidth(1); } if(me->drawflag & ME_DRAWCREASES) { - draw_dm_creases(cageDM); + draw_dm_creases(em, cageDM); } if(me->drawflag & ME_DRAWBWEIGHTS) { - draw_dm_bweights(scene, cageDM); + draw_dm_bweights(em, scene, cageDM); + } + + if(me->drawflag & ME_DRAW_PINS) { + UI_ThemeColor(TH_PIN); + glLineWidth(2); + + draw_dm_edges_pins(em, cageDM, me); + + glColor3ub(0,0,0); + glLineWidth(1); } - draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act); + draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act); } if(em) { // XXX retopo_matrix_update(v3d); @@ -2658,11 +2827,15 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object if(me->drawflag & ME_DRAWNORMALS) { UI_ThemeColor(TH_NORMAL); - draw_dm_face_normals(scene, cageDM); + draw_dm_face_normals(em, scene, cageDM); } if(me->drawflag & ME_DRAW_VNORMALS) { UI_ThemeColor(TH_NORMAL); - draw_dm_vert_normals(scene, cageDM); + draw_dm_vert_normals(em, scene, cageDM); + } + if(me->drawflag & ME_DRAW_PINS) { + UI_ThemeColor(TH_PIN); + draw_dm_vert_pins(em, cageDM, me); } if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG)) @@ -2675,7 +2848,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object GPU_disable_material(); } - EM_free_index_arrays(); + EDBM_free_index_arrays(em); } /* Mesh drawing routines */ @@ -2730,7 +2903,7 @@ static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base totvert = dm->getNumVerts(dm); totedge = dm->getNumEdges(dm); - totface = dm->getNumFaces(dm); + totface = dm->getNumTessFaces(dm); /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */ if(dt!=OB_SHADED) @@ -2925,7 +3098,7 @@ static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base Object *ob= base->object; Object *obedit= scene->obedit; Mesh *me= ob->data; - EditMesh *em= me->edit_mesh; + BMEditMesh *em= me->edit_btmesh; int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha; if(obedit && ob!=obedit && ob->data==obedit->data) { @@ -2937,9 +3110,9 @@ static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base DerivedMesh *finalDM, *cageDM; if (obedit!=ob) - finalDM = cageDM = editmesh_get_derived_base(ob, em); + finalDM = cageDM = editbmesh_get_derived_base(ob, em); else - cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM, + cageDM = editbmesh_get_derived_cage_and_final(scene, ob, em, &finalDM, v3d->customdata_mask); if(dt>OB_WIRE) { @@ -6005,44 +6178,49 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) static void bbs_mesh_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s) { - int offset = (intptr_t) userData; - EditVert *eve = EM_get_vert_for_index(index); + void **ptrs = userData; + int offset = (intptr_t) ptrs[0]; + BMVert *eve = EDBM_get_vert_for_index(ptrs[1], index); - if (eve->h==0) { + if (!BM_TestHFlag(eve, BM_HIDDEN)) { WM_set_framebuffer_index_color(offset+index); bglVertex3fv(co); } } -static void bbs_mesh_verts(DerivedMesh *dm, int offset) +static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset) { + void *ptrs[2] = {(void*)(intptr_t) offset, em}; + glPointSize( UI_GetThemeValuef(TH_VERTEX_SIZE) ); bglBegin(GL_POINTS); - dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, (void*)(intptr_t) offset); + dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, ptrs); bglEnd(); glPointSize(1.0); } static int bbs_mesh_wire__setDrawOptions(void *userData, int index) { - int offset = (intptr_t) userData; - EditEdge *eed = EM_get_edge_for_index(index); + void **ptrs = userData; + int offset = (intptr_t) ptrs[0]; + BMEdge *eed = EDBM_get_edge_for_index(ptrs[1], index); - if (eed->h==0) { + if (!BM_TestHFlag(eed, BM_HIDDEN)) { WM_set_framebuffer_index_color(offset+index); return 1; } else { return 0; } } -static void bbs_mesh_wire(DerivedMesh *dm, int offset) +static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset) { - dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, (void*)(intptr_t) offset); + void *ptrs[2] = {(void*)(intptr_t) offset, em}; + dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, ptrs); } static int bbs_mesh_solid__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r) { - if (EM_get_face_for_index(index)->h==0) { - if (userData) { + if (!BM_TestHFlag(EDBM_get_face_for_index(((void**)userData)[0], index), BM_HIDDEN)) { + if (((void**)userData)[1]) { WM_set_framebuffer_index_color(index+1); } return 1; @@ -6053,9 +6231,9 @@ static int bbs_mesh_solid__setSolidDrawOptions(void *userData, int index, int *d static void bbs_mesh_solid__drawCenter(void *userData, int index, float *cent, float *no) { - EditFace *efa = EM_get_face_for_index(index); + BMFace *efa = EDBM_get_face_for_index(((void**)userData)[0], index); - if (efa->h==0 && efa->fgonf!=EM_FGON) { + if (!BM_TestHFlag(efa, BM_HIDDEN)) { WM_set_framebuffer_index_color(index+1); bglVertex3fv(cent); @@ -6063,23 +6241,26 @@ static void bbs_mesh_solid__drawCenter(void *userData, int index, float *cent, f } /* two options, facecolors or black */ -static void bbs_mesh_solid_EM(Scene *scene, View3D *v3d, Object *ob, DerivedMesh *dm, int facecol) +static void bbs_mesh_solid_EM(BMEditMesh *em, Scene *scene, View3D *v3d, + Object *ob, DerivedMesh *dm, int facecol) { + void *ptrs[2] = {em, NULL}; //second one being null means to draw black cpack(0); if (facecol) { - dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*)(intptr_t) 1, 0); + ptrs[1] = (void*)(intptr_t) 1; + dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, ptrs, 0); if( CHECK_OB_DRAWFACEDOT(scene, v3d, ob->dt) ) { glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE)); bglBegin(GL_POINTS); - dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, NULL); + dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, ptrs); bglEnd(); } } else { - dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*) 0, 0); + dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, ptrs, 0); } } @@ -6087,7 +6268,11 @@ static int bbs_mesh_solid__setDrawOpts(void *userData, int index, int *drawSmoot { Mesh *me = userData; - if (!(me->mface[index].flag&ME_HIDE)) { + /*sanity check*/ + if (index >= me->totpoly) + return 0; + + if (!(me->mpoly[index].flag&ME_HIDE)) { return 1; } else { return 0; @@ -6118,7 +6303,7 @@ static void bbs_mesh_solid(Scene *scene, View3D *v3d, Object *ob) if( !GPU_buffer_legacy(dm) ) { int *index = DM_get_face_data_layer(dm, CD_ORIGINDEX); int ind; - colors = MEM_mallocN(dm->getNumFaces(dm)*sizeof(MCol)*4,"bbs_mesh_solid"); + colors = MEM_mallocN(dm->getNumTessFaces(dm)*sizeof(MCol)*4,"bbs_mesh_solid"); for(i=0;i<dm->getNumFaces(dm);i++) { if( index != 0 ) ind = index[i]; @@ -6163,36 +6348,36 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec { if(ob->mode & OB_MODE_EDIT) { Mesh *me= ob->data; - EditMesh *em= me->edit_mesh; + BMEditMesh *em= me->edit_btmesh; - DerivedMesh *dm = editmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH); + DerivedMesh *dm = editbmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH); - EM_init_index_arrays(em, 1, 1, 1); + EDBM_init_index_arrays(em, 1, 1, 1); - bbs_mesh_solid_EM(scene, v3d, ob, dm, ts->selectmode & SCE_SELECT_FACE); + bbs_mesh_solid_EM(em, scene, v3d, ob, dm, ts->selectmode & SCE_SELECT_FACE); if(ts->selectmode & SCE_SELECT_FACE) - em_solidoffs = 1+em->totface; + bm_solidoffs = 1+em->bm->totface; else - em_solidoffs= 1; + bm_solidoffs= 1; bglPolygonOffset(rv3d->dist, 1.0); // we draw edges always, for loop (select) tools - bbs_mesh_wire(dm, em_solidoffs); - em_wireoffs= em_solidoffs + em->totedge; + bbs_mesh_wire(em, dm, bm_solidoffs); + bm_wireoffs= bm_solidoffs + em->bm->totedge; // we draw verts if vert select mode or if in transform (for snap). if(ts->selectmode & SCE_SELECT_VERTEX || G.moving & G_TRANSFORM_EDIT) { - bbs_mesh_verts(dm, em_wireoffs); - em_vertoffs= em_wireoffs + em->totvert; + bbs_mesh_verts(em, dm, bm_wireoffs); + bm_vertoffs= bm_wireoffs + em->bm->totvert; } - else em_vertoffs= em_wireoffs; + else bm_vertoffs= bm_wireoffs; bglPolygonOffset(rv3d->dist, 0.0); dm->release(dm); - EM_free_index_arrays(); + EDBM_free_index_arrays(em); } else bbs_mesh_solid(scene, v3d, ob); } @@ -6218,7 +6403,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r int glsl; if(ob->mode & OB_MODE_EDIT) - edm= editmesh_get_derived_base(ob, me->edit_mesh); + edm= editbmesh_get_derived_base(ob, me->edit_btmesh); else dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 0cdf849d453..c50aa4fc2ed 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -70,6 +70,7 @@ #include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "BIF_gl.h" @@ -167,31 +168,30 @@ static void v3d_editvertex_buts(const bContext *C, uiLayout *layout, View3D *v3d if(ob->type==OB_MESH) { Mesh *me= ob->data; - EditMesh *em = BKE_mesh_get_editmesh(me); - EditVert *eve, *evedef=NULL; - EditEdge *eed; + BMEditMesh *em = me->edit_btmesh; + BMesh *bm = em->bm; + BMVert *eve, *evedef=NULL; + BMEdge *eed; + BMIter iter; - eve= em->verts.first; - while(eve) { - if(eve->f & SELECT) { + BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) { + if(BM_TestHFlag(eve, BM_SELECT)) { evedef= eve; tot++; VecAddf(median, median, eve->co); } - eve= eve->next; } - eed= em->edges.first; - while(eed) { - if((eed->f & SELECT)) { + + BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) { + if(BM_TestHFlag(eed, BM_SELECT)) { totedge++; median[3]+= eed->crease; } - eed= eed->next; } /* check for defgroups */ if(evedef) - dvert= CustomData_em_get(&em->vdata, evedef->data, CD_MDEFORMVERT); + dvert= CustomData_bmesh_get(&em->bm->vdata, evedef->head.data, CD_MDEFORMVERT); if(tot==1 && dvert && dvert->totweight) { bDeformGroup *dg; int i, max=1, init=1; @@ -215,8 +215,6 @@ static void v3d_editvertex_buts(const bContext *C, uiLayout *layout, View3D *v3d tfp->defweightp= &dvert->dw[0].weight; } } - - BKE_mesh_end_editmesh(me, em); } else if(ob->type==OB_CURVE || ob->type==OB_SURF) { Curve *cu= ob->data; diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index c0a0241c74c..95900e6faa3 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -65,6 +65,7 @@ #include "BKE_particle.h" #include "BKE_screen.h" #include "BKE_utildefines.h" /* for VECCOPY */ +#include "BKE_tessmesh.h" #include "ED_armature.h" #include "ED_particle.h" @@ -1680,12 +1681,12 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event) View3D *v3d= sa->spacedata.first; Object *obedit = CTX_data_edit_object(C); Object *ob = CTX_data_active_object(C); - EditMesh *em= NULL; + BMEditMesh *em= NULL; int bit, ctrl= win->eventstate->ctrl, shift= win->eventstate->shift; PointerRNA props_ptr; if(obedit && obedit->type==OB_MESH) { - em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + em= ((Mesh *)obedit->data)->edit_btmesh; } /* watch it: if sa->win does not exist, check that when calling direct drawing routines */ @@ -1743,7 +1744,7 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event) if(shift==0 || em->selectmode==0) em->selectmode= SCE_SELECT_VERTEX; ts->selectmode= em->selectmode; - EM_selectmode_set(em); + EDBM_selectmode_set(em); WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); ED_undo_push(C, "Selectmode Set: Vertex"); } @@ -1752,12 +1753,12 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event) if(em) { if(shift==0 || em->selectmode==0){ if( (em->selectmode ^ SCE_SELECT_EDGE) == SCE_SELECT_VERTEX){ - if(ctrl) EM_convertsel(em, SCE_SELECT_VERTEX,SCE_SELECT_EDGE); + if(ctrl) EDBM_convertsel(em, SCE_SELECT_VERTEX,SCE_SELECT_EDGE); } em->selectmode = SCE_SELECT_EDGE; } ts->selectmode= em->selectmode; - EM_selectmode_set(em); + EDBM_selectmode_set(em); WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); ED_undo_push(C, "Selectmode Set: Edge"); } @@ -1766,12 +1767,12 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event) if(em) { if( shift==0 || em->selectmode==0){ if( ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)){ - if(ctrl) EM_convertsel(em, (ts->selectmode ^ SCE_SELECT_FACE),SCE_SELECT_FACE); + if(ctrl) EDBM_convertsel(em, (ts->selectmode ^ SCE_SELECT_FACE),SCE_SELECT_FACE); } em->selectmode = SCE_SELECT_FACE; } ts->selectmode= em->selectmode; - EM_selectmode_set(em); + EDBM_selectmode_set(em); WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); ED_undo_push(C, "Selectmode Set: Face"); } @@ -1859,9 +1860,6 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event) } break; } - - if(obedit && obedit->type==OB_MESH) - BKE_mesh_end_editmesh(obedit->data, em); } static void view3d_header_pulldowns(const bContext *C, uiBlock *block, Object *ob, int *xcoord, int yco) @@ -2163,7 +2161,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) /* selection modus */ if(obedit && (obedit->type == OB_MESH)) { - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; uiBlockBeginAlign(block); uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, xco,yco,XIC,YIC, &em->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode (Ctrl Tab 1)"); @@ -2180,8 +2178,6 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) xco+= XIC; uiBlockEndAlign(block); header_xco_step(ar, &xco, &yco, &maxco, XIC); - - BKE_mesh_end_editmesh(obedit->data, em); } else if(ob && ob->mode & OB_MODE_PARTICLE_EDIT) { uiBlockBeginAlign(block); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 8dc7d6a0518..eb85c4ff722 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -64,6 +64,7 @@ #include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "RE_pipeline.h" // make_stars @@ -80,10 +81,10 @@ #include "ED_particle.h" #include "ED_mesh.h" #include "ED_object.h" -#include "ED_retopo.h" #include "ED_screen.h" #include "ED_types.h" #include "ED_util.h" +#include "ED_retopo.h" #include "ED_mball.h" #include "UI_interface.h" @@ -152,43 +153,49 @@ static void BIF_undo_push() {} /* local prototypes */ -void EM_backbuf_checkAndSelectVerts(EditMesh *em, int select) +void EM_backbuf_checkAndSelectVerts(BMEditMesh *em, int select) { - EditVert *eve; - int index= em_wireoffs; - - for(eve= em->verts.first; eve; eve= eve->next, index++) { - if(eve->h==0) { - if(EM_check_backbuf(index)) { - eve->f = select?(eve->f|1):(eve->f&~1); + BMVert *eve; + BMIter iter; + int index= bm_wireoffs; + + eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL); + for ( ; eve; eve=BMIter_Step(&iter), index++) { + if(!BM_TestHFlag(eve, BM_HIDDEN)) { + if(EDBM_check_backbuf(index)) { + BM_Select_Vert(em->bm, eve, select); } } } } -void EM_backbuf_checkAndSelectEdges(EditMesh *em, int select) +void EM_backbuf_checkAndSelectEdges(BMEditMesh *em, int select) { - EditEdge *eed; - int index= em_solidoffs; - - for(eed= em->edges.first; eed; eed= eed->next, index++) { - if(eed->h==0) { - if(EM_check_backbuf(index)) { - EM_select_edge(eed, select); + BMEdge *eed; + BMIter iter; + int index= bm_solidoffs; + + eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL); + for ( ; eed; eed=BMIter_Step(&iter), index++) { + if(!BM_TestHFlag(eed, BM_HIDDEN)) { + if(EDBM_check_backbuf(index)) { + BM_Select_Edge(em->bm, eed, select); } } } } -void EM_backbuf_checkAndSelectFaces(EditMesh *em, int select) +void EM_backbuf_checkAndSelectFaces(BMEditMesh *em, int select) { - EditFace *efa; + BMFace *efa; + BMIter iter; int index= 1; - for(efa= em->faces.first; efa; efa= efa->next, index++) { - if(efa->h==0) { - if(EM_check_backbuf(index)) { - EM_select_face_fgon(em, efa, select); + efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL); + for ( ; efa; efa=BMIter_Step(&iter), index++) { + if(!BM_TestHFlag(efa, BM_HIDDEN)) { + if(EDBM_check_backbuf(index)) { + BM_Select_Face(em->bm, efa, select); } } } @@ -201,7 +208,7 @@ void EM_backbuf_checkAndSelectTFaces(Mesh *me, int select) if (mface) { for(a=1; a<=me->totface; a++, mface++) { - if(EM_check_backbuf(a)) { + if(EDBM_check_backbuf(a)) { mface->flag = select?(mface->flag|ME_FACE_SEL):(mface->flag&~ME_FACE_SEL); } } @@ -402,53 +409,52 @@ void lasso_select_boundbox(rcti *rect, short mcords[][2], short moves) } } -static void do_lasso_select_mesh__doSelectVert(void *userData, EditVert *eve, int x, int y, int index) +static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, int x, int y, int index) { struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } *data = userData; if (BLI_in_rcti(data->rect, x, y) && lasso_inside(data->mcords, data->moves, x, y)) { - eve->f = data->select?(eve->f|1):(eve->f&~1); + BM_Select_Vert(data->vc.em->bm, eve, data->select); } } -static void do_lasso_select_mesh__doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index) +static void do_lasso_select_mesh__doSelectEdge(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index) { struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } *data = userData; - if (EM_check_backbuf(em_solidoffs+index)) { + if (EM_check_backbuf(bm_solidoffs+index)) { if (data->pass==0) { if ( edge_fully_inside_rect(data->rect, x0, y0, x1, y1) && lasso_inside(data->mcords, data->moves, x0, y0) && lasso_inside(data->mcords, data->moves, x1, y1)) { - EM_select_edge(eed, data->select); + BM_Select_Edge(data->vc.em->bm, eed, data->select); data->done = 1; } } else { if (lasso_inside_edge(data->mcords, data->moves, x0, y0, x1, y1)) { - EM_select_edge(eed, data->select); + BM_Select_Edge(data->vc.em->bm, eed, data->select); } } } } -static void do_lasso_select_mesh__doSelectFace(void *userData, EditFace *efa, int x, int y, int index) +static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, int x, int y, int index) { struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } *data = userData; if (BLI_in_rcti(data->rect, x, y) && lasso_inside(data->mcords, data->moves, x, y)) { - EM_select_face_fgon(data->vc.em, efa, data->select); + BM_Select_Face(data->vc.em->bm, efa, data->select); } } static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves, short select) { struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } data; - ToolSettings *ts= vc->scene->toolsettings; rcti rect; int bbsel; lasso_select_boundbox(&rect, mcords, moves); /* set editmesh */ - vc->em= ((Mesh *)vc->obedit->data)->edit_mesh; + vc->em= ((Mesh *)vc->obedit->data)->edit_btmesh; data.vc= *vc; data.rect = ▭ @@ -463,14 +469,14 @@ static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - if(ts->selectmode & SCE_SELECT_VERTEX) { + if(vc->scene->toolsettings->selectmode & SCE_SELECT_VERTEX) { if (bbsel) { EM_backbuf_checkAndSelectVerts(vc->em, select); } else { mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, 1); } } - if(ts->selectmode & SCE_SELECT_EDGE) { + if(vc->scene->toolsettings->selectmode & SCE_SELECT_EDGE) { /* Does both bbsel and non-bbsel versions (need screen cos for both) */ data.pass = 0; @@ -482,7 +488,7 @@ static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves } } - if(ts->selectmode & SCE_SELECT_FACE) { + if(vc->scene->toolsettings->selectmode & SCE_SELECT_FACE) { if (bbsel) { EM_backbuf_checkAndSelectFaces(vc->em, select); } else { @@ -491,7 +497,7 @@ static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves } EM_free_backbuf(); - EM_selectmode_flush(vc->em); + EDBM_selectmode_flush(vc->em); } #if 0 @@ -658,7 +664,7 @@ static void do_lasso_select_facemode(ViewContext *vc, short mcords[][2], short m if(me==NULL || me->mtface==NULL) return; if(me->totface==0) return; - em_vertoffs= me->totface+1; /* max index array */ + bm_vertoffs= me->totface+1; /* max index array */ lasso_select_boundbox(&rect, mcords, moves); EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); @@ -728,6 +734,12 @@ void view3d_lasso_select(bContext *C, ViewContext *vc, short mcords[][2], short } +static EnumPropertyItem lasso_select_types[] = { + {0, "SELECT", 0, "Select", ""}, + {1, "DESELECT", 0, "Deselect", ""}, + {0, NULL, 0, NULL, NULL} +}; + /* lasso operator gives properties, but since old code works with short array we convert */ @@ -754,7 +766,7 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op) /* setup view context for argument to callbacks */ view3d_set_viewcontext(C, &vc); - select= !RNA_boolean_get(op->ptr, "deselect"); + select= RNA_enum_is_equal(C, op->ptr, "type", "SELECT"); view3d_lasso_select(C, &vc, mcords, i, select); return OPERATOR_FINISHED; @@ -777,7 +789,7 @@ void VIEW3D_OT_select_lasso(wmOperatorType *ot) ot->flag= OPTYPE_UNDO; RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", ""); - RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect rather than select items."); + RNA_def_enum(ot->srna, "type", lasso_select_types, 0, "Type", ""); } @@ -1285,43 +1297,47 @@ static void do_lattice_box_select(ViewContext *vc, rcti *rect, int select) lattice_foreachScreenVert(vc, do_lattice_box_select__doSelect, &data); } -static void do_mesh_box_select__doSelectVert(void *userData, EditVert *eve, int x, int y, int index) +static void do_mesh_box_select__doSelectVert(void *userData, BMVert *eve, int x, int y, int index) { struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData; if (BLI_in_rcti(data->rect, x, y)) { - eve->f = data->select?(eve->f|1):(eve->f&~1); + BM_Select_Vert(data->vc.em->bm, eve, data->select); } } -static void do_mesh_box_select__doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index) +static void do_mesh_box_select__doSelectEdge(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index) { struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData; - if(EM_check_backbuf(em_solidoffs+index)) { + if(EM_check_backbuf(bm_solidoffs+index)) { if (data->pass==0) { if (edge_fully_inside_rect(data->rect, x0, y0, x1, y1)) { - EM_select_edge(eed, data->select); + BM_Select_Edge(data->vc.em->bm, eed, data->select); data->done = 1; } } else { if (edge_inside_rect(data->rect, x0, y0, x1, y1)) { - EM_select_edge(eed, data->select); + BM_Select_Edge(data->vc.em->bm, eed, data->select); } } } } -static void do_mesh_box_select__doSelectFace(void *userData, EditFace *efa, int x, int y, int index) + +static void +do_mesh_box_select__doSelectFace(void *userData, BMFace + *efa, int x, int y, + int index) + { struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData; if (BLI_in_rcti(data->rect, x, y)) { - EM_select_face_fgon(data->vc.em, efa, data->select); + BM_Select_Face(data->vc.em->bm, efa, data->select); } } static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select) { struct { ViewContext vc; rcti *rect; short select, pass, done; } data; - ToolSettings *ts= vc->scene->toolsettings; int bbsel; data.vc= *vc; @@ -1330,17 +1346,17 @@ static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select) data.pass = 0; data.done = 0; - bbsel= EM_init_backbuf_border(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax); + bbsel= EDBM_init_backbuf_border(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax); ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - if(ts->selectmode & SCE_SELECT_VERTEX) { + if(vc->scene->toolsettings->selectmode & SCE_SELECT_VERTEX) { if (bbsel) { EM_backbuf_checkAndSelectVerts(vc->em, select); } else { mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, 1); } } - if(ts->selectmode & SCE_SELECT_EDGE) { + if(vc->scene->toolsettings->selectmode & SCE_SELECT_EDGE) { /* Does both bbsel and non-bbsel versions (need screen cos for both) */ data.pass = 0; @@ -1352,7 +1368,7 @@ static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select) } } - if(ts->selectmode & SCE_SELECT_FACE) { + if(vc->scene->toolsettings->selectmode & SCE_SELECT_FACE) { if(bbsel) { EM_backbuf_checkAndSelectFaces(vc->em, select); } else { @@ -1362,7 +1378,7 @@ static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select) EM_free_backbuf(); - EM_selectmode_flush(vc->em); + EDBM_selectmode_flush(vc->em); } static int view3d_borderselect_exec(bContext *C, wmOperator *op) @@ -1402,7 +1418,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) if(obedit) { if(obedit->type==OB_MESH) { Mesh *me= obedit->data; - vc.em= me->edit_mesh; + vc.em= me->edit_btmesh; do_mesh_box_select(&vc, &rect, (val==LEFTMOUSE)); // if (EM_texFaceCheck()) WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); @@ -1488,7 +1504,6 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) } } - ED_armature_sync_selection(arm->edbo); } else if(obedit->type==OB_LATTICE) { do_lattice_box_select(&vc, &rect, val==LEFTMOUSE); @@ -1574,6 +1589,11 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) /* *****************Selection Operators******************* */ +static EnumPropertyItem prop_select_types[] = { + {0, "EXCLUSIVE", 0, "Exclusive", ""}, + {1, "EXTEND", 0, "Extend", ""}, + {0, NULL, 0, NULL, NULL} +}; /* ****** Border Select ****** */ void VIEW3D_OT_select_border(wmOperatorType *ot) @@ -1609,8 +1629,8 @@ void VIEW3D_OT_select_border(wmOperatorType *ot) static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event) { Object *obedit= CTX_data_edit_object(C); - Object *obact= CTX_data_active_object(C); short extend= RNA_boolean_get(op->ptr, "extend"); + Object *obact= CTX_data_active_object(C); short center= RNA_boolean_get(op->ptr, "center"); short enumerate= RNA_boolean_get(op->ptr, "enumerate"); @@ -1661,38 +1681,37 @@ void VIEW3D_OT_select(wmOperatorType *ot) /* -------------------- circle select --------------------------------------------- */ -static void mesh_circle_doSelectVert(void *userData, EditVert *eve, int x, int y, int index) +static void mesh_circle_doSelectVert(void *userData, BMVert *eve, int x, int y, int index) { struct {ViewContext *vc; short select, mval[2]; float radius; } *data = userData; int mx = x - data->mval[0], my = y - data->mval[1]; float r = sqrt(mx*mx + my*my); if (r<=data->radius) { - eve->f = data->select?(eve->f|1):(eve->f&~1); + BM_Select_Vert(data->vc->em->bm, eve, data->select); } } -static void mesh_circle_doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index) +static void mesh_circle_doSelectEdge(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index) { struct {ViewContext *vc; short select, mval[2]; float radius; } *data = userData; if (edge_inside_circle(data->mval[0], data->mval[1], (short) data->radius, x0, y0, x1, y1)) { - EM_select_edge(eed, data->select); + BM_Select_Edge(data->vc->em->bm, eed, data->select); } } -static void mesh_circle_doSelectFace(void *userData, EditFace *efa, int x, int y, int index) +static void mesh_circle_doSelectFace(void *userData, BMFace *efa, int x, int y, int index) { struct {ViewContext *vc; short select, mval[2]; float radius; } *data = userData; int mx = x - data->mval[0], my = y - data->mval[1]; float r = sqrt(mx*mx + my*my); if (r<=data->radius) { - EM_select_face_fgon(data->vc->em, efa, data->select); + BM_Select_Face(data->vc->em->bm, efa, data->select); } } static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, float rad) { - ToolSettings *ts= vc->scene->toolsettings; int bbsel; Object *ob= vc->obact; @@ -1700,11 +1719,11 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa Mesh *me = ob?ob->data:NULL; if (me) { - em_vertoffs= me->totface+1; /* max index array */ + bm_vertoffs= me->totface+1; /* max index array */ - bbsel= EM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0)); - EM_backbuf_checkAndSelectTFaces(me, selecting==LEFTMOUSE); - EM_free_backbuf(); + //bbsel= EDBM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0)); + //BMESH_TODO EM_backbuf_checkAndSelectTFaces(me, selecting==LEFTMOUSE); + //EDBM_free_backbuf(); // XXX object_tface_flags_changed(OBACT, 0); } @@ -1712,17 +1731,17 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa else { struct {ViewContext *vc; short select, mval[2]; float radius; } data; - bbsel= EM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0)); + bbsel= EDBM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0)); + vc->em= ((Mesh *)vc->obedit->data)->edit_btmesh; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - vc->em= ((Mesh *)vc->obedit->data)->edit_mesh; - data.select = selecting; data.mval[0] = mval[0]; data.mval[1] = mval[1]; data.radius = rad; + data.vc = vc; - if(ts->selectmode & SCE_SELECT_VERTEX) { + if(vc->scene->toolsettings->selectmode & SCE_SELECT_VERTEX) { if(bbsel) { EM_backbuf_checkAndSelectVerts(vc->em, selecting==LEFTMOUSE); } else { @@ -1730,7 +1749,7 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa } } - if(ts->selectmode & SCE_SELECT_EDGE) { + if(vc->scene->toolsettings->selectmode & SCE_SELECT_EDGE) { if (bbsel) { EM_backbuf_checkAndSelectEdges(vc->em, selecting==LEFTMOUSE); } else { @@ -1738,7 +1757,7 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa } } - if(ts->selectmode & SCE_SELECT_FACE) { + if(vc->scene->toolsettings->selectmode & SCE_SELECT_FACE) { if(bbsel) { EM_backbuf_checkAndSelectFaces(vc->em, selecting==LEFTMOUSE); } else { @@ -1746,8 +1765,8 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa } } - EM_free_backbuf(); - EM_selectmode_flush(vc->em); + EDBM_free_backbuf(); + EDBM_selectmode_flush(vc->em); } } diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 767f18649fa..128597d4d5f 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -1,5 +1,5 @@ /** - * $Id$ + * $Id: view3d_snap.c 18967 2009-02-14 13:07:09Z ton $ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -66,6 +66,7 @@ #include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "WM_api.h" #include "WM_types.h" @@ -107,10 +108,10 @@ static void special_transvert_update(Scene *scene, Object *obedit) if(obedit) { DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - + if(obedit->type==OB_MESH) { Mesh *me= obedit->data; - recalc_editnormals(me->edit_mesh); // does face centers too + BM_Compute_Normals(me->edit_btmesh->bm); // does face centers too } else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { Curve *cu= obedit->data; @@ -178,7 +179,8 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode) BPoint *bp; TransVert *tv=NULL; MetaElem *ml; - EditVert *eve; + BMVert *eve; + BMIter iter; EditBone *ebo; float total, center[3], centroid[3]; int a; @@ -190,45 +192,70 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode) if(obedit->type==OB_MESH) { Mesh *me= obedit->data; - EditMesh *em= me->edit_mesh; + BMEditMesh *em= me->edit_btmesh; + BMesh *bm = em->bm; int proptrans= 0; // transform now requires awareness for select mode, so we tag the f1 flags in verts tottrans= 0; - if(em->selectmode & SCE_SELECT_VERTEX) { - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->h==0 && (eve->f & SELECT)) { - eve->f1= SELECT; + if(em->bm->selectmode & SCE_SELECT_VERTEX) { + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (; eve; eve=BMIter_Step(&iter)) { + if(!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT)) { + BMINDEX_SET(eve, 1); tottrans++; } - else eve->f1= 0; + else BMINDEX_SET(eve, 0); } } - else if(em->selectmode & SCE_SELECT_EDGE) { - EditEdge *eed; - for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0; - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->h==0 && (eed->f & SELECT)) eed->v1->f1= eed->v2->f1= SELECT; + else if(em->bm->selectmode & SCE_SELECT_EDGE) { + BMEdge *eed; + + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (; eve; eve=BMIter_Step(&iter)) + BMINDEX_SET(eve, 0); + + eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); + for (; eed; eed=BMIter_Step(&iter)) { + if(!BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SELECT)) + BMINDEX_SET(eed->v1, 0), BMINDEX_SET(eed->v2, 0); } - for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++; + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (; eve; eve=BMIter_Step(&iter)) + if(BMINDEX_GET(eve)) tottrans++; } else { - EditFace *efa; - for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0; - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->h==0 && (efa->f & SELECT)) { - efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT; - if(efa->v4) efa->v4->f1= SELECT; + BMFace *efa; + + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (; eve; eve=BMIter_Step(&iter)) + BMINDEX_SET(eve, 0); + + efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); + for (; efa; efa=BMIter_Step(&iter)) { + if(!BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT)) { + BMIter liter; + BMLoop *l; + + l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, efa); + for (; l; l=BMIter_Step(&iter)) { + BMINDEX_SET(l->v, 1); + } } } - for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++; + + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (; eve; eve=BMIter_Step(&iter)) + if(BMINDEX_GET(eve)) tottrans++; } /* proportional edit exception... */ if((mode & 1) && tottrans) { - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->h==0) { - eve->f1 |= 2; + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (; eve; eve=BMIter_Step(&iter)) { + if(BMINDEX_GET(eve)) tottrans++; + if(!BM_TestHFlag(eve, BM_HIDDEN)) { + BMINDEX_SET(eve, BMINDEX_GET(eve)|2); proptrans++; } } @@ -239,13 +266,14 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode) if(tottrans) { tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts"); - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->f1) { + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (; eve; eve=BMIter_Step(&iter)) { + if(BMINDEX_GET(eve)) { VECCOPY(tv->oldloc, eve->co); tv->loc= eve->co; if(eve->no[0]!=0.0 || eve->no[1]!=0.0 ||eve->no[2]!=0.0) tv->nor= eve->no; // note this is a hackish signal (ton) - tv->flag= eve->f1 & SELECT; + tv->flag= BMINDEX_GET(eve) & SELECT; tv++; } } @@ -302,7 +330,7 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode) int totmalloc= 0; for(nu= cu->editnurb->first; nu; nu= nu->next) { - if(nu->type == CU_BEZIER) + if((nu->type & 7)==CU_BEZIER) totmalloc += 3*nu->pntsu; else totmalloc += nu->pntsu*nu->pntsv; @@ -311,7 +339,7 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode) nu= cu->editnurb->first; while(nu) { - if(nu->type == CU_BEZIER) { + if((nu->type & 7)==CU_BEZIER) { a= nu->pntsu; bezt= nu->bezt; while(a--) { @@ -514,7 +542,7 @@ static int snap_sel_to_grid(bContext *C, wmOperator *op) /* auto-keyframing */ // XXX autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0); - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); + DAG_id_flush_update(ob->data, OB_RECALC_DATA); } else { ob->recalc |= OB_RECALC_OB; @@ -555,7 +583,6 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot) /* identifiers */ ot->name= "Snap Selection to Grid"; - ot->description= "Snap selected item(s) to nearest grid node."; ot->idname= "VIEW3D_OT_snap_selected_to_grid"; /* api callbacks */ @@ -641,7 +668,7 @@ static int snap_sel_to_curs(bContext *C, wmOperator *op) /* auto-keyframing */ // XXX autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0); - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); + DAG_id_flush_update(ob->data, OB_RECALC_DATA); } else { ob->recalc |= OB_RECALC_OB; @@ -681,7 +708,6 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot) /* identifiers */ ot->name= "Snap Selection to Cursor"; - ot->description= "Snap selected item(s) to cursor."; ot->idname= "VIEW3D_OT_snap_selected_to_cursor"; /* api callbacks */ @@ -717,7 +743,6 @@ void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot) /* identifiers */ ot->name= "Snap Cursor to Grid"; - ot->description= "Snap cursor to nearest grid node."; ot->idname= "VIEW3D_OT_snap_cursor_to_grid"; /* api callbacks */ @@ -824,7 +849,6 @@ void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot) /* identifiers */ ot->name= "Snap Cursor to Selected"; - ot->description= "Snap cursor to center of selected item(s)."; ot->idname= "VIEW3D_OT_snap_cursor_to_selected"; /* api callbacks */ @@ -850,10 +874,10 @@ static int snap_curs_to_active(bContext *C, wmOperator *op) if (obedit->type == OB_MESH) { /* check active */ Mesh *me= obedit->data; - EditSelection ese; + BMEditSelection ese; - if (EM_get_actSelection(me->edit_mesh, &ese)) { - EM_editselection_center(curs, &ese); + if (EDBM_get_actSelection(me->edit_btmesh, &ese)) { + EDBM_editselection_center(me->edit_btmesh, curs, &ese); } Mat4MulVecfl(obedit->obmat, curs); @@ -874,7 +898,6 @@ void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot) /* identifiers */ ot->name= "Snap Cursor to Active"; - ot->description= "Snap cursor to active item."; ot->idname= "VIEW3D_OT_snap_cursor_to_active"; /* api callbacks */ @@ -1033,7 +1056,7 @@ static int snap_selected_to_center(bContext *C, wmOperator *op) /* auto-keyframing */ ob->pose->flag |= POSE_DO_UNLOCK; // XXX autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0); - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); + DAG_id_flush_update(ob->data, OB_RECALC_DATA); } else { ob->recalc |= OB_RECALC_OB; @@ -1074,7 +1097,6 @@ void VIEW3D_OT_snap_selected_to_center(wmOperatorType *ot) /* identifiers */ ot->name= "Snap Selection to Center"; - ot->description= "Snap selected items to selections geometric center."; ot->idname= "VIEW3D_OT_snap_selected_to_center"; /* api callbacks */ @@ -1141,7 +1163,6 @@ void VIEW3D_OT_snap_menu(wmOperatorType *ot) { /* identifiers */ ot->name= "Snap Menu"; - ot->description= "Display snap menu."; ot->idname= "VIEW3D_OT_snap_menu"; /* api callbacks */ diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 8b378f05eb2..8aafe24e702 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -623,8 +623,8 @@ void view3d_project_float(ARegion *ar, float *vec, float *adr, float mat[4][4]) { float vec4[4]; - adr[0]= IS_CLIPPED; VECCOPY(vec4, vec); + adr[0]= IS_CLIPPED; vec4[3]= 1.0; Mat4MulVec4fl(mat, vec4); diff --git a/source/blender/editors/transform/SConscript b/source/blender/editors/transform/SConscript index b2dee8c3358..8501a95b981 100644 --- a/source/blender/editors/transform/SConscript +++ b/source/blender/editors/transform/SConscript @@ -6,6 +6,6 @@ sources = env.Glob('*.c') incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../render/extern/include #/intern/guardedalloc' -incs += ' ../../gpu ../../makesrna' +incs += ' ../../gpu ../../makesrna ../../bmesh' env.BlenderLib ( 'bf_editors_transform', sources, Split(incs), [], libtype=['core'], priority=[40] )
\ No newline at end of file diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 4c24d366162..7128bd9c6a9 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -3947,8 +3947,9 @@ int BoneEnvelope(TransInfo *t, short mval[2]) static int createSlideVerts(TransInfo *t) { +#if 0 Mesh *me = t->obedit->data; - EditMesh *em = me->edit_mesh; + BMEditMesh *em = me->edit_btmesh; EditFace *efa; EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL; EditVert *ev, *nearest = NULL; @@ -4415,10 +4416,12 @@ static int createSlideVerts(TransInfo *t) t->customData = sld; return 1; +#endif } void freeSlideVerts(TransInfo *t) { +#if 0 TransDataSlideUv *suv; SlideData *sld = t->customData; int uvlay_idx; @@ -4447,6 +4450,7 @@ void freeSlideVerts(TransInfo *t) MEM_freeN(sld); t->customData = NULL; +#endif } void initEdgeSlide(TransInfo *t) @@ -4478,6 +4482,7 @@ void initEdgeSlide(TransInfo *t) int doEdgeSlide(TransInfo *t, float perc) { +#if 0 Mesh *me= t->obedit->data; EditMesh *em = me->edit_mesh; SlideData *sld = t->customData; @@ -4586,7 +4591,7 @@ int doEdgeSlide(TransInfo *t, float perc) } } - +#endif return 1; } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 496a9665371..764256c476d 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -100,6 +100,7 @@ #include "BKE_bmesh.h" #include "BKE_context.h" #include "BKE_report.h" +#include "BKE_tessmesh.h" //#include "BIF_editview.h" //#include "BIF_editlattice.h" @@ -138,6 +139,7 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_editVert.h" +#include "BLI_array.h" //#include "editmesh.h" // @@ -148,6 +150,7 @@ extern ListBase editelems; #include "transform.h" +#include "bmesh.h" #include "BLO_sys_types.h" // for intptr_t support @@ -1890,22 +1893,54 @@ static void editmesh_set_connectivity_distance(EditMesh *em, int total, float *v } /* loop-in-a-loop I know, but we need it! (ton) */ -static void get_face_center(float *cent, EditMesh *em, EditVert *eve) + static void get_face_center(float *centout, BMesh *bm, BMVert *eve) + { - EditFace *efa; + BMFace *efa; + BMLoop *l; + BMIter iter; + float cent[3] = {0.0, 0.0, 0.0}; - for(efa= em->faces.first; efa; efa= efa->next) - if(efa->f & SELECT) - if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve) - break; - if(efa) { - VECCOPY(cent, efa->cent); + efa = BMIter_New(&iter, bm, BM_FACES_OF_VERT, eve); + if (efa) { + l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa); + for ( ; l; l=BMIter_Step(&iter)) { + VECADD(cent, cent, l->v->co); + } + + VECMUL(cent, 1.0f / (float)efa->len); } + + if (cent[0] == 0.0f && cent[1] == 0.0f && cent[2] == 0.0f) cent[2] = 1.0f; + VECCOPY(centout, cent); } +#define VertsToTransData(t, td, em, eve) \ + td->flag = 0;\ + td->loc = eve->co;\ + VECCOPY(td->center, td->loc);\ + if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))\ + get_face_center(td->center, em, eve);\ + VECCOPY(td->iloc, td->loc);\ + VECCOPY(td->axismtx[2], eve->no);\ + td->axismtx[0][0] =\ + td->axismtx[0][1] =\ + td->axismtx[0][2] =\ + td->axismtx[1][0] =\ + td->axismtx[1][1] =\ + td->axismtx[1][2] = 0.0f;\ + td->ext = NULL;\ + td->val = NULL;\ + td->extra = NULL;\ + if (t->mode == TFM_BWEIGHT) {\ + td->val = &(eve->bweight);\ + td->ival = eve->bweight;\ + } + +#if 0 //way to overwrite what data is edited with transform //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key) -static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert *eve) +inline void VertsToTransData(TransInfo *t, TransData *td, BMesh *em, BMVert *eve) { td->flag = 0; //if(key) @@ -1935,6 +1970,7 @@ static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert td->ival = eve->bweight; } } +#endif /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */ @@ -1971,13 +2007,13 @@ static float *get_crazy_mapped_editverts(TransInfo *t) /* disable subsurf temporal, get mapped cos, and enable it */ if(modifiers_disable_subsurf_temporary(t->obedit)) { /* need to make new derivemesh */ - makeDerivedMesh(t->scene, t->obedit, me->edit_mesh, CD_MASK_BAREMESH); + makeDerivedMesh(t->scene, t->obedit, me->edit_btmesh, CD_MASK_BAREMESH); } /* now get the cage */ - dm= editmesh_get_derived_cage(t->scene, t->obedit, me->edit_mesh, CD_MASK_BAREMESH); + dm= editbmesh_get_derived_cage(t->scene, t->obedit, me->edit_btmesh, CD_MASK_BAREMESH); - vertexcos= MEM_mallocN(3*sizeof(float)*me->edit_mesh->totvert, "vertexcos map"); + vertexcos= MEM_mallocN(3*sizeof(float)*me->edit_btmesh->bm->totvert, "vertexcos map"); dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos); dm->release(dm); @@ -2006,17 +2042,18 @@ static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, } #undef TAN_MAKE_VEC -static void set_crazyspace_quats(EditMesh *em, float *origcos, float *mappedcos, float *quats) +static void set_crazyspace_quats(BMEditMesh *em, float *origcos, float *mappedcos, float *quats) { - EditVert *eve, *prev; - EditFace *efa; +#if 0 + BMVert *eve, *prev; + BMFace *efa; float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4; intptr_t index= 0; /* two abused locations in vertices */ for(eve= em->verts.first; eve; eve= eve->next, index++) { eve->tmp.p = NULL; - eve->prev= (EditVert *)index; + eve->prev= (BMVert *)index; } /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */ @@ -2074,7 +2111,7 @@ static void set_crazyspace_quats(EditMesh *em, float *origcos, float *mappedcos, /* restore abused prev pointer */ for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next) eve->prev= prev; - +#endif } void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) { @@ -2106,13 +2143,16 @@ static void createTransEditVerts(bContext *C, TransInfo *t) { ToolSettings *ts = CTX_data_tool_settings(C); TransData *tob = NULL; - EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh; - EditVert *eve; - EditVert **nears = NULL; - EditVert *eve_act = NULL; + BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh; + BMesh *bm = em->bm; + BMVert *eve; + BMVert **nears = NULL; + BMIter iter; + BMVert *eve_act = NULL; float *vectors = NULL, *mappedcos = NULL, *quats= NULL; float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL; - int count=0, countsel=0, a, totleft; + int count=0, countsel=0, a, totleft, *selstate = NULL; + BLI_array_declare(selstate); int propmode = t->flag & T_PROP_EDIT; int mirror = 0; @@ -2123,36 +2163,56 @@ static void createTransEditVerts(bContext *C, TransInfo *t) // transform now requires awareness for select mode, so we tag the f1 flags in verts if(ts->selectmode & SCE_SELECT_VERTEX) { - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->h==0 && (eve->f & SELECT)) - eve->f1= SELECT; + BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) { + if(!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT)) + BMINDEX_SET(eve, SELECT); else - eve->f1= 0; + BMINDEX_SET(eve, 0); } } else if(ts->selectmode & SCE_SELECT_EDGE) { - EditEdge *eed; - for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0; - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->h==0 && (eed->f & SELECT)) - eed->v1->f1= eed->v2->f1= SELECT; + BMEdge *eed; + + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for( ; eve; eve=BMIter_Step(&iter)) BMINDEX_SET(eve, 0); + + eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); + for( ; eed; eed=BMIter_Step(&iter)) { + if(!BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SELECT)) + BMINDEX_SET(eed->v1, SELECT), BMINDEX_SET(eed->v2, SELECT); } } else { - EditFace *efa; - for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0; - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->h==0 && (efa->f & SELECT)) { - efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT; - if(efa->v4) efa->v4->f1= SELECT; + BMFace *efa; + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for( ; eve; eve=BMIter_Step(&iter)) BMINDEX_SET(eve, 0); + + efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); + for( ; efa; efa=BMIter_Step(&iter)) { + if(!BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT)) { + BMIter liter; + BMLoop *l; + + l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, efa); + for (; l; l=BMIter_Step(&liter)) { + BMINDEX_SET(l->v, SELECT); + } } } } - /* now we can count */ - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->h==0) { - if(eve->f1) countsel++; + /* now we can count. we store selection state in selstate, since + get_crazy_mapped_editverts messes up the index state of the + verts*/ + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for(a=0; eve; eve=BMIter_Step(&iter), a++) { + BLI_array_growone(selstate); + + if(!BM_TestHFlag(eve, BM_HIDDEN)) { + if(BMINDEX_GET(eve)) { + selstate[a] = 1; + countsel++; + } if(propmode) count++; } } @@ -2161,10 +2221,10 @@ static void createTransEditVerts(bContext *C, TransInfo *t) if (countsel==0) return; /* check active */ - if (em->selected.last) { - EditSelection *ese = em->selected.last; + if (em->bm->selected.last) { + BMEditSelection *ese = em->bm->selected.last; if ( ese->type == EDITVERT ) { - eve_act = (EditVert *)ese->data; + eve_act = (BMVert *)ese->data; } } @@ -2174,7 +2234,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t) /* allocating scratch arrays */ vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors"); - nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears"); + nears = (BMVert**)MEM_mallocN(t->total * sizeof(BMVert*), "scratch nears"); } else t->total = countsel; tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)"); @@ -2182,7 +2242,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t) Mat3CpyMat4(mtx, t->obedit->obmat); Mat3Inv(smtx, mtx); - if(propmode) editmesh_set_connectivity_distance(em, t->total, vectors, nears); + //BMESH_TODO if(propmode) editmesh_set_connectivity_distance(em, t->total, vectors, nears); /* detect CrazySpace [tm] */ if(propmode==0) { @@ -2190,7 +2250,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t) if(modifiers_isDeformed(t->scene, t->obedit)) { /* check if we can use deform matrices for modifier from the start up to stack, they are more accurate than quats */ - totleft= editmesh_get_first_deform_matrices(t->obedit, em, &defmats, &defcos); + totleft= editbmesh_get_first_deform_matrices(t->obedit, em, &defmats, &defcos); /* if we still have more modifiers, also do crazyspace correction with quats, relative to the coordinates after @@ -2211,8 +2271,9 @@ static void createTransEditVerts(bContext *C, TransInfo *t) /* find out which half we do */ if(mirror) { - for (eve=em->verts.first; eve; eve=eve->next) { - if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) { + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for(a=0; eve; eve=BMIter_Step(&iter), a++) { + if(!BM_TestHFlag(eve, BM_HIDDEN) && selstate[a] && eve->co[0]!=0.0f) { if(eve->co[0]<0.0f) { t->mirror = -1; @@ -2223,36 +2284,44 @@ static void createTransEditVerts(bContext *C, TransInfo *t) } } - for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) { - if(eve->h==0) { - if(propmode || eve->f1) { - VertsToTransData(t, tob, em, eve); + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for(a=0; eve; eve=BMIter_Step(&iter), a++) { + if(!BM_TestHFlag(eve, BM_HIDDEN)) { + if(propmode || selstate[a]) { + VertsToTransData(t, tob, bm, eve); + + /* pinned */ + if(BM_TestHFlag(eve,BM_PINNED)) tob->flag |= TD_SKIP; /* selected */ - if(eve->f1) tob->flag |= TD_SELECTED; + if(selstate[a]) tob->flag |= TD_SELECTED; /* active */ if(eve == eve_act) tob->flag |= TD_ACTIVE; if(propmode) { + /*BMESH_TODO + this has to do with edge connectivity + PEP mode, I think. -joeedh if (eve->f2) { float vec[3]; VECCOPY(vec, E_VEC(eve)); Mat3MulVecfl(mtx, vec); tob->dist= VecLength(vec); } - else { + else {*/ tob->flag |= TD_NOTCONNECTED; tob->dist = MAXFLOAT; - } + //} } /* CrazySpace */ - if(defmats || (quats && eve->tmp.p)) { + if(defmats) { // || (quats && eve->tmp.p)) { float mat[3][3], imat[3][3], qmat[3][3]; /* use both or either quat and defmat correction */ - if(quats && eve->tmp.f) { + //BMESH_TODO, need to restore this quats thing + /*if(quats && eve->tmp.f) { QuatToMat3(eve->tmp.p, qmat); if(defmats) @@ -2261,7 +2330,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t) else Mat3MulMat3(mat, mtx, qmat); } - else + else*/ Mat3MulMat3(mat, mtx, defmats[a]); Mat3Inv(imat, mat); @@ -2275,10 +2344,12 @@ static void createTransEditVerts(bContext *C, TransInfo *t) } /* Mirror? */ - if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) { - EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, tob->iloc); /* initializes octree on first call */ - if(vmir != eve) tob->extra = vmir; - } + + //BMESH_TODO + //if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) { + // EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, tob->iloc); /* initializes octree on first call */ + // if(vmir != eve) tob->extra = vmir; + //} tob++; } } @@ -2300,11 +2371,14 @@ static void createTransEditVerts(bContext *C, TransInfo *t) MEM_freeN(vectors); MEM_freeN(nears); } + /* crazy space free */ if(quats) MEM_freeN(quats); if(defmats) MEM_freeN(defmats); + + BLI_array_free(selstate); } /* *** NODE EDITOR *** */ @@ -2443,30 +2517,33 @@ static void createTransUVs(bContext *C, TransInfo *t) Scene *scene = CTX_data_scene(C); TransData *td = NULL; TransData2D *td2d = NULL; - MTFace *tf; + MTexPoly *tf; + MLoopUV *luv; + BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; int count=0, countsel=0; int propmode = t->flag & T_PROP_EDIT; - EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh; - EditFace *efa; - if(!ED_uvedit_test(t->obedit)) return; /* count */ - for (efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - if(uvedit_face_visible(scene, ima, efa, tf)) { - efa->tmp.p = tf; + if(!uvedit_face_visible(scene, ima, efa, tf)) { + BMINDEX_SET(efa, 0); + continue; + } + + BMINDEX_SET(efa, 1); + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if (uvedit_uv_selected(em, scene, l)) + countsel++; - if (uvedit_uv_selected(scene, efa, tf, 0)) countsel++; - if (uvedit_uv_selected(scene, efa, tf, 1)) countsel++; - if (uvedit_uv_selected(scene, efa, tf, 2)) countsel++; - if (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) countsel++; if(propmode) - count += (efa->v4)? 4: 3; - } else { - efa->tmp.p = NULL; + count += efa->len; } } @@ -2485,20 +2562,17 @@ static void createTransUVs(bContext *C, TransInfo *t) td= t->data; td2d= t->data2d; - for (efa= em->faces.first; efa; efa= efa->next) { - if ((tf=(MTFace *)efa->tmp.p)) { - if (propmode) { - UVsToTransData(sima, td++, td2d++, tf->uv[0], uvedit_uv_selected(scene, efa, tf, 0)); - UVsToTransData(sima, td++, td2d++, tf->uv[1], uvedit_uv_selected(scene, efa, tf, 1)); - UVsToTransData(sima, td++, td2d++, tf->uv[2], uvedit_uv_selected(scene, efa, tf, 2)); - if(efa->v4) - UVsToTransData(sima, td++, td2d++, tf->uv[3], uvedit_uv_selected(scene, efa, tf, 3)); - } else { - if(uvedit_uv_selected(scene, efa, tf, 0)) UVsToTransData(sima, td++, td2d++, tf->uv[0], 1); - if(uvedit_uv_selected(scene, efa, tf, 1)) UVsToTransData(sima, td++, td2d++, tf->uv[1], 1); - if(uvedit_uv_selected(scene, efa, tf, 2)) UVsToTransData(sima, td++, td2d++, tf->uv[2], 1); - if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) UVsToTransData(sima, td++, td2d++, tf->uv[3], 1); - } + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BMINDEX_GET(efa)) + continue; + + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if (!propmode && !uvedit_uv_selected(em, scene, l)) + continue; + + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + UVsToTransData(sima, td++, td2d++, luv->uv, uvedit_uv_selected(em, scene, l)); } } @@ -4773,7 +4847,7 @@ void special_aftertrans_update(TransInfo *t) if (t->obedit->type == OB_MESH) { - EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh; + BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh; /* table needs to be created for each edit command, since vertices can move etc */ mesh_octree_table(t->obedit, em, NULL, 'e'); } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 8dc71710d82..66b46ab5b96 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -85,6 +85,7 @@ #include "BKE_object.h" #include "BKE_utildefines.h" #include "BKE_context.h" +#include "BKE_tessmesh.h" #include "ED_anim_api.h" #include "ED_armature.h" @@ -126,19 +127,19 @@ void getViewVector(TransInfo *t, float coord[3], float vec[3]) if (t->persp != V3D_ORTHO) { float p1[4], p2[4]; - + VECCOPY(p1, coord); p1[3] = 1.0f; VECCOPY(p2, p1); p2[3] = 1.0f; Mat4MulVec4fl(t->viewmat, p2); - + p2[0] = 2.0f * p2[0]; p2[1] = 2.0f * p2[1]; p2[2] = 2.0f * p2[2]; - + Mat4MulVec4fl(t->viewinv, p2); - + VecSubf(vec, p1, p2); } else { @@ -154,11 +155,11 @@ static void clipMirrorModifier(TransInfo *t, Object *ob) ModifierData *md= ob->modifiers.first; float tolerance[3] = {0.0f, 0.0f, 0.0f}; int axis = 0; - + for (; md; md=md->next) { if (md->type==eModifierType_Mirror) { MirrorModifierData *mmd = (MirrorModifierData*) md; - + if(mmd->flag & MOD_MIR_CLIPPING) { axis = 0; if(mmd->flag & MOD_MIR_AXIS_X) { @@ -177,35 +178,35 @@ static void clipMirrorModifier(TransInfo *t, Object *ob) float mtx[4][4], imtx[4][4]; int i; TransData *td = t->data; - + if (mmd->mirror_ob) { float obinv[4][4]; - + Mat4Invert(obinv, mmd->mirror_ob->obmat); Mat4MulMat4(mtx, ob->obmat, obinv); Mat4Invert(imtx, mtx); } - + for(i = 0 ; i < t->total; i++, td++) { int clip; float loc[3], iloc[3]; - + if (td->flag & TD_NOACTION) break; if (td->loc==NULL) break; - + if (td->flag & TD_SKIP) continue; - + VecCopyf(loc, td->loc); VecCopyf(iloc, td->iloc); - + if (mmd->mirror_ob) { VecMat4MulVecfl(loc, mtx, loc); VecMat4MulVecfl(iloc, mtx, iloc); } - + clip = 0; if(axis & 1) { if(fabs(iloc[0])<=tolerance[0] || @@ -214,7 +215,7 @@ static void clipMirrorModifier(TransInfo *t, Object *ob) clip = 1; } } - + if(axis & 2) { if(fabs(iloc[1])<=tolerance[1] || loc[1]*iloc[1]<0.0f) { @@ -237,19 +238,20 @@ static void clipMirrorModifier(TransInfo *t, Object *ob) } } } - + } } } } /* assumes obedit set to mesh object */ -static void editmesh_apply_to_mirror(TransInfo *t) +static void editbmesh_apply_to_mirror(TransInfo *t) { TransData *td = t->data; - EditVert *eve; + BMVert *eve; + BMIter iter; int i; - + for(i = 0 ; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) break; @@ -257,9 +259,9 @@ static void editmesh_apply_to_mirror(TransInfo *t) break; if (td->flag & TD_SKIP) continue; - + eve = td->extra; - if (eve) { + if(eve) { eve->co[0]= -td->loc[0]; eve->co[1]= td->loc[1]; eve->co[2]= td->loc[2]; @@ -268,9 +270,9 @@ static void editmesh_apply_to_mirror(TransInfo *t) if (td->flag & TD_MIRROR_EDGE) { td->loc[0] = 0; - } } } +} /* tags the given ID block for refreshes (if applicable) due to * Animation Editor editing @@ -641,183 +643,184 @@ void recalcData(TransInfo *t) } if (t->obedit) { - if ELEM(t->obedit->type, OB_CURVE, OB_SURF) { - Curve *cu= t->obedit->data; - Nurb *nu= cu->editnurb->first; + if ELEM(t->obedit->type, OB_CURVE, OB_SURF) { + Curve *cu= t->obedit->data; + Nurb *nu= cu->editnurb->first; - DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */ + DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */ - if (t->state == TRANS_CANCEL) { - while(nu) { - calchandlesNurb(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */ - nu= nu->next; - } - } else { - /* Normal updating */ - while(nu) { - test2DNurb(nu); - calchandlesNurb(nu); - nu= nu->next; - } + if (t->state == TRANS_CANCEL) { + while(nu) { + calchandlesNurb(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */ + nu= nu->next; + } + } else { + /* Normal updating */ + while(nu) { + test2DNurb(nu); + calchandlesNurb(nu); + nu= nu->next; } } - else if(t->obedit->type==OB_LATTICE) { - Lattice *la= t->obedit->data; - DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */ - - if(la->editlatt->flag & LT_OUTSIDE) outside_lattice(la->editlatt); - } - else if (t->obedit->type == OB_MESH) { - EditMesh *em = ((Mesh*)t->obedit->data)->edit_mesh; + } + else if(t->obedit->type==OB_LATTICE) { + Lattice *la= t->obedit->data; + DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */ + + if(la->editlatt->flag & LT_OUTSIDE) outside_lattice(la->editlatt); + } + else if (t->obedit->type == OB_MESH) { + BMEditMesh *em = ((Mesh*)t->obedit->data)->edit_btmesh; /* mirror modifier clipping? */ if(t->state != TRANS_CANCEL) { clipMirrorModifier(t, t->obedit); } if((t->options & CTX_NO_MIRROR) == 0 && (t->flag & T_MIRROR)) - editmesh_apply_to_mirror(t); - + editbmesh_apply_to_mirror(t); + DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */ - - recalc_editnormals(em); + + EDBM_RecalcNormals(em); + BMEdit_RecalcTesselation(em); } - else if(t->obedit->type==OB_ARMATURE) { /* no recalc flag, does pose */ - bArmature *arm= t->obedit->data; - ListBase *edbo = arm->edbo; - EditBone *ebo; - TransData *td = t->data; - int i; + else if(t->obedit->type==OB_ARMATURE) { /* no recalc flag, does pose */ + bArmature *arm= t->obedit->data; + ListBase *edbo = arm->edbo; + EditBone *ebo; + TransData *td = t->data; + int i; - /* Ensure all bones are correctly adjusted */ - for (ebo = edbo->first; ebo; ebo = ebo->next){ + /* Ensure all bones are correctly adjusted */ + for (ebo = edbo->first; ebo; ebo = ebo->next){ - if ((ebo->flag & BONE_CONNECTED) && ebo->parent){ - /* If this bone has a parent tip that has been moved */ - if (ebo->parent->flag & BONE_TIPSEL){ - VECCOPY (ebo->head, ebo->parent->tail); - if(t->mode==TFM_BONE_ENVELOPE) ebo->rad_head= ebo->parent->rad_tail; - } - /* If this bone has a parent tip that has NOT been moved */ - else{ - VECCOPY (ebo->parent->tail, ebo->head); - if(t->mode==TFM_BONE_ENVELOPE) ebo->parent->rad_tail= ebo->rad_head; - } + if ((ebo->flag & BONE_CONNECTED) && ebo->parent){ + /* If this bone has a parent tip that has been moved */ + if (ebo->parent->flag & BONE_TIPSEL){ + VECCOPY (ebo->head, ebo->parent->tail); + if(t->mode==TFM_BONE_ENVELOPE) ebo->rad_head= ebo->parent->rad_tail; } - - /* on extrude bones, oldlength==0.0f, so we scale radius of points */ - ebo->length= VecLenf(ebo->head, ebo->tail); - if(ebo->oldlength==0.0f) { - ebo->rad_head= 0.25f*ebo->length; - ebo->rad_tail= 0.10f*ebo->length; - ebo->dist= 0.25f*ebo->length; - if(ebo->parent) { - if(ebo->rad_head > ebo->parent->rad_tail) - ebo->rad_head= ebo->parent->rad_tail; - } + /* If this bone has a parent tip that has NOT been moved */ + else{ + VECCOPY (ebo->parent->tail, ebo->head); + if(t->mode==TFM_BONE_ENVELOPE) ebo->parent->rad_tail= ebo->rad_head; } - else if(t->mode!=TFM_BONE_ENVELOPE) { - /* if bones change length, lets do that for the deform distance as well */ - ebo->dist*= ebo->length/ebo->oldlength; - ebo->rad_head*= ebo->length/ebo->oldlength; - ebo->rad_tail*= ebo->length/ebo->oldlength; - ebo->oldlength= ebo->length; + } + + /* on extrude bones, oldlength==0.0f, so we scale radius of points */ + ebo->length= VecLenf(ebo->head, ebo->tail); + if(ebo->oldlength==0.0f) { + ebo->rad_head= 0.25f*ebo->length; + ebo->rad_tail= 0.10f*ebo->length; + ebo->dist= 0.25f*ebo->length; + if(ebo->parent) { + if(ebo->rad_head > ebo->parent->rad_tail) + ebo->rad_head= ebo->parent->rad_tail; } } + else if(t->mode!=TFM_BONE_ENVELOPE) { + /* if bones change length, lets do that for the deform distance as well */ + ebo->dist*= ebo->length/ebo->oldlength; + ebo->rad_head*= ebo->length/ebo->oldlength; + ebo->rad_tail*= ebo->length/ebo->oldlength; + ebo->oldlength= ebo->length; + } + } - if (t->mode != TFM_BONE_ROLL) + if (t->mode != TFM_BONE_ROLL) + { + /* fix roll */ + for(i = 0; i < t->total; i++, td++) { - /* fix roll */ - for(i = 0; i < t->total; i++, td++) + if (td->extra) { - if (td->extra) - { - float vec[3], up_axis[3]; - float qrot[4]; + float vec[3], up_axis[3]; + float qrot[4]; - ebo = td->extra; - VECCOPY(up_axis, td->axismtx[2]); + ebo = td->extra; + VECCOPY(up_axis, td->axismtx[2]); - if (t->mode != TFM_ROTATION) - { - VecSubf(vec, ebo->tail, ebo->head); - Normalize(vec); - RotationBetweenVectorsToQuat(qrot, td->axismtx[1], vec); - QuatMulVecf(qrot, up_axis); - } - else - { - Mat3MulVecfl(t->mat, up_axis); - } - - ebo->roll = ED_rollBoneToVector(ebo, up_axis); + if (t->mode != TFM_ROTATION) + { + VecSubf(vec, ebo->tail, ebo->head); + Normalize(vec); + RotationBetweenVectorsToQuat(qrot, td->axismtx[1], vec); + QuatMulVecf(qrot, up_axis); + } + else + { + Mat3MulVecfl(t->mat, up_axis); } + + ebo->roll = ED_rollBoneToVector(ebo, up_axis); } } + } - if(arm->flag & ARM_MIRROR_EDIT) - transform_armature_mirror_update(t->obedit); + if(arm->flag & ARM_MIRROR_EDIT) + transform_armature_mirror_update(t->obedit); - } - else - DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */ } - else if( (t->flag & T_POSE) && t->poseobj) { - Object *ob= t->poseobj; - bArmature *arm= ob->data; + else + DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */ + } + else if( (t->flag & T_POSE) && t->poseobj) { + Object *ob= t->poseobj; + bArmature *arm= ob->data; - /* if animtimer is running, and the object already has animation data, - * check if the auto-record feature means that we should record 'samples' - * (i.e. uneditable animation values) - */ - // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes? - if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) { - int targetless_ik= (t->flag & T_AUTOIK); // XXX this currently doesn't work, since flags aren't set yet! - - animrecord_check_state(t->scene, &ob->id, t->animtimer); - autokeyframe_pose_cb_func(t->scene, (View3D *)t->view, ob, t->mode, targetless_ik); - } + /* if animtimer is running, and the object already has animation data, + * check if the auto-record feature means that we should record 'samples' + * (i.e. uneditable animation values) + */ + // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes? + if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) { + int targetless_ik= (t->flag & T_AUTOIK); // XXX this currently doesn't work, since flags aren't set yet! - /* old optimize trick... this enforces to bypass the depgraph */ - if (!(arm->flag & ARM_DELAYDEFORM)) { - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */ - } - else - where_is_pose(scene, ob); + animrecord_check_state(t->scene, &ob->id, t->animtimer); + autokeyframe_pose_cb_func(t->scene, (View3D *)t->view, ob, t->mode, targetless_ik); } - else { - for(base= FIRSTBASE; base; base= base->next) { - Object *ob= base->object; + + /* old optimize trick... this enforces to bypass the depgraph */ + if (!(arm->flag & ARM_DELAYDEFORM)) { + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */ + } + else + where_is_pose(scene, ob); + } + else { + for(base= FIRSTBASE; base; base= base->next) { + Object *ob= base->object; - /* this flag is from depgraph, was stored in initialize phase, handled in drawview.c */ - if(base->flag & BA_HAS_RECALC_OB) - ob->recalc |= OB_RECALC_OB; - if(base->flag & BA_HAS_RECALC_DATA) - ob->recalc |= OB_RECALC_DATA; + /* this flag is from depgraph, was stored in initialize phase, handled in drawview.c */ + if(base->flag & BA_HAS_RECALC_OB) + ob->recalc |= OB_RECALC_OB; + if(base->flag & BA_HAS_RECALC_DATA) + ob->recalc |= OB_RECALC_DATA; - /* if object/base is selected */ - if ((base->flag & SELECT) || (ob->flag & SELECT)) { - /* if animtimer is running, and the object already has animation data, - * check if the auto-record feature means that we should record 'samples' - * (i.e. uneditable animation values) - */ - // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes? - if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) { - animrecord_check_state(t->scene, &ob->id, t->animtimer); - autokeyframe_ob_cb_func(t->scene, (View3D *)t->view, ob, t->mode); - } + /* if object/base is selected */ + if ((base->flag & SELECT) || (ob->flag & SELECT)) { + /* if animtimer is running, and the object already has animation data, + * check if the auto-record feature means that we should record 'samples' + * (i.e. uneditable animation values) + */ + // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes? + if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) { + animrecord_check_state(t->scene, &ob->id, t->animtimer); + autokeyframe_ob_cb_func(t->scene, (View3D *)t->view, ob, t->mode); } - - /* proxy exception */ - if(ob->proxy) - ob->proxy->recalc |= ob->recalc; - if(ob->proxy_group) - group_tag_recalc(ob->proxy_group->dup_group); } + + /* proxy exception */ + if(ob->proxy) + ob->proxy->recalc |= ob->recalc; + if(ob->proxy_group) + group_tag_recalc(ob->proxy_group->dup_group); } + } if(((View3D*)t->view)->drawtype == OB_SHADED) - reshadeall_displist(t->scene); - } + reshadeall_displist(t->scene); +} } void drawLine(TransInfo *t, float *center, float *dir, char axis, short options) @@ -828,18 +831,18 @@ void drawLine(TransInfo *t, float *center, float *dir, char axis, short options) if (t->spacetype == SPACE_VIEW3D) { View3D *v3d = t->view; - + glPushMatrix(); - + //if(t->obedit) glLoadMatrixf(t->obedit->obmat); // sets opengl viewing - - + + VecCopyf(v3, dir); VecMulf(v3, v3d->far); - + VecSubf(v2, center, v3); VecAddf(v1, center, v3); - + if (options & DRAWLIGHT) { col[0] = col[1] = col[2] = 220; } @@ -848,13 +851,13 @@ void drawLine(TransInfo *t, float *center, float *dir, char axis, short options) } UI_make_axis_color(col, col2, axis); glColor3ubv((GLubyte *)col2); - + setlinestyle(0); glBegin(GL_LINE_STRIP); glVertex3fv(v1); glVertex3fv(v2); glEnd(); - + glPopMatrix(); } } @@ -871,33 +874,33 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) ARegion *ar = CTX_wm_region(C); ScrArea *sa = CTX_wm_area(C); Object *obedit = CTX_data_edit_object(C); - + /* moving: is shown in drawobject() (transform color) */ // TRANSFORM_FIX_ME // if(obedit || (t->flag & T_POSE) ) G.moving= G_TRANSFORM_EDIT; // else if(G.f & G_PARTICLEEDIT) G.moving= G_TRANSFORM_PARTICLE; // else G.moving= G_TRANSFORM_OBJ; - + t->scene = sce; t->sa = sa; t->ar = ar; t->obedit = obedit; t->settings = ts; - + t->data = NULL; t->ext = NULL; - + t->helpline = HLP_NONE; - + t->flag = 0; - + t->redraw = 1; /* redraw first time */ - + if (event) { t->imval[0] = event->x - t->ar->winrct.xmin; t->imval[1] = event->y - t->ar->winrct.ymin; - + t->event_type = event->type; } else @@ -905,45 +908,45 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) t->imval[0] = 0; t->imval[1] = 0; } - + t->con.imval[0] = t->imval[0]; t->con.imval[1] = t->imval[1]; - + t->mval[0] = t->imval[0]; t->mval[1] = t->imval[1]; - + t->transform = NULL; t->handleEvent = NULL; - + t->total = 0; - + t->val = 0.0f; - + t->vec[0] = t->vec[1] = t->vec[2] = 0.0f; - + t->center[0] = t->center[1] = t->center[2] = 0.0f; - + Mat3One(t->mat); - + t->spacetype = sa->spacetype; if(t->spacetype == SPACE_VIEW3D) { View3D *v3d = sa->spacedata.first; - + t->view = v3d; t->animtimer= CTX_wm_screen(C)->animtimer; - + if(v3d->flag & V3D_ALIGN) t->flag |= T_V3D_ALIGN; t->around = v3d->around; - + if (op && RNA_struct_find_property(op->ptr, "constraint_orientation") && RNA_property_is_set(op->ptr, "constraint_orientation")) { t->current_orientation = RNA_enum_get(op->ptr, "constraint_orientation"); - + if (t->current_orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C) - 1) { t->current_orientation = V3D_MANIP_GLOBAL; @@ -965,10 +968,10 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) { // XXX for now, get View2D from the active region t->view = &ar->v2d; - + t->around = V3D_CENTER; } - + if (op && RNA_struct_find_property(op->ptr, "mirror") && RNA_property_is_set(op->ptr, "mirror")) { if (RNA_boolean_get(op->ptr, "mirror")) @@ -986,40 +989,40 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) t->mirror = 1; } } - + /* setting PET flag only if property exist in operator. Otherwise, assume it's not supported */ if (op && RNA_struct_find_property(op->ptr, "proportional")) { if (RNA_property_is_set(op->ptr, "proportional")) { - switch(RNA_enum_get(op->ptr, "proportional")) - { - case 2: /* XXX connected constant */ - t->flag |= T_PROP_CONNECTED; - case 1: /* XXX prop on constant */ - t->flag |= T_PROP_EDIT; - break; - } - } - else + switch(RNA_enum_get(op->ptr, "proportional")) { + case 2: /* XXX connected constant */ + t->flag |= T_PROP_CONNECTED; + case 1: /* XXX prop on constant */ + t->flag |= T_PROP_EDIT; + break; + } + } + else + { if ((t->options & CTX_NO_PET) == 0 && (ts->proportional != PROP_EDIT_OFF)) { - t->flag |= T_PROP_EDIT; - + t->flag |= T_PROP_EDIT; + if(ts->proportional == PROP_EDIT_CONNECTED) - t->flag |= T_PROP_CONNECTED; // yes i know, has to become define - } - } - - if (op && RNA_struct_find_property(op->ptr, "proportional_size") && RNA_property_is_set(op->ptr, "proportional_size")) - { - t->prop_size = RNA_float_get(op->ptr, "proportional_size"); + t->flag |= T_PROP_CONNECTED; // yes i know, has to become define } - else - { - t->prop_size = ts->proportional_size; - } - + } + + if (op && RNA_struct_find_property(op->ptr, "proportional_size") && RNA_property_is_set(op->ptr, "proportional_size")) + { + t->prop_size = RNA_float_get(op->ptr, "proportional_size"); + } + else + { + t->prop_size = ts->proportional_size; + } + /* TRANSFORM_FIX_ME rna restrictions */ if (t->prop_size <= 0) @@ -1027,25 +1030,25 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) t->prop_size = 1.0f; } - if (op && RNA_struct_find_property(op->ptr, "proportional_editing_falloff") && RNA_property_is_set(op->ptr, "proportional_editing_falloff")) - { - t->prop_mode = RNA_enum_get(op->ptr, "proportional_editing_falloff"); - } - else - { - t->prop_mode = ts->prop_mode; - } + if (op && RNA_struct_find_property(op->ptr, "proportional_editing_falloff") && RNA_property_is_set(op->ptr, "proportional_editing_falloff")) + { + t->prop_mode = RNA_enum_get(op->ptr, "proportional_editing_falloff"); + } + else + { + t->prop_mode = ts->prop_mode; + } } else /* add not pet option to context when not available */ { t->options |= CTX_NO_PET; } - + setTransformViewMatrices(t); initNumInput(&t->num); initNDofInput(&t->ndof); - + return 1; } @@ -1053,16 +1056,16 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) void postTrans (TransInfo *t) { TransData *td; - + if (t->draw_handle) { ED_region_draw_cb_exit(t->ar->type, t->draw_handle); } - + /* postTrans can be called when nothing is selected, so data is NULL already */ if (t->data) { int a; - + /* since ipokeys are optional on objects, we mallocced them per trans-data */ for(a=0, td= t->data; a<t->total; a++, td++) { if (td->flag & TD_BEZTRIPLE) @@ -1070,13 +1073,13 @@ void postTrans (TransInfo *t) } MEM_freeN(t->data); } - + if (t->ext) MEM_freeN(t->ext); if (t->data2d) { MEM_freeN(t->data2d); t->data2d= NULL; } - + if(t->spacetype==SPACE_IMAGE) { SpaceImage *sima= t->sa->spacedata.first; if(sima->flag & SI_LIVE_UNWRAP) @@ -1092,14 +1095,13 @@ void postTrans (TransInfo *t) t->customFree(t); } else if (t->customData) { - MEM_freeN(t->customData); - } -} + MEM_freeN(t->customData); + }} void applyTransObjects(TransInfo *t) { TransData *td; - + for (td = t->data; td < t->data + t->total; td++) { VECCOPY(td->iloc, td->loc); if (td->ext->rot) { @@ -1127,27 +1129,27 @@ static void restoreElement(TransData *td) { if (td->ext->size) { VECCOPY(td->ext->size, td->ext->isize); } - if (td->ext->quat) { - QUATCOPY(td->ext->quat, td->ext->iquat); + if (td->ext->quat) { + QUATCOPY(td->ext->quat, td->ext->iquat); + } } - } - + if (td->flag & TD_BEZTRIPLE) { *(td->hdata->h1) = td->hdata->ih1; *(td->hdata->h2) = td->hdata->ih2; } -} + } void restoreTransObjects(TransInfo *t) { TransData *td; - + for (td = t->data; td < t->data + t->total; td++) { restoreElement(td); } - + Mat3One(t->mat); - + recalcData(t); } @@ -1156,7 +1158,7 @@ void calculateCenter2D(TransInfo *t) if (t->flag & (T_EDIT|T_POSE)) { Object *ob= t->obedit?t->obedit:t->poseobj; float vec[3]; - + VECCOPY(vec, t->center); Mat4MulVecfl(ob->obmat, vec); projectIntView(t, vec, t->center2d); @@ -1169,21 +1171,21 @@ void calculateCenter2D(TransInfo *t) void calculateCenterCursor(TransInfo *t) { float *cursor; - + cursor = give_cursor(t->scene, t->view); VECCOPY(t->center, cursor); - + /* If edit or pose mode, move cursor in local space */ if (t->flag & (T_EDIT|T_POSE)) { Object *ob = t->obedit?t->obedit:t->poseobj; float mat[3][3], imat[3][3]; - + VecSubf(t->center, t->center, ob->obmat[3]); Mat3CpyMat4(mat, ob->obmat); Mat3Inv(imat, mat); Mat3MulVecfl(imat, t->center); } - + calculateCenter2D(t); } @@ -1191,15 +1193,15 @@ void calculateCenterCursor2D(TransInfo *t) { View2D *v2d= t->view; float aspx=1.0, aspy=1.0; - + if(t->spacetype==SPACE_IMAGE) /* only space supported right now but may change */ ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy); - + if (v2d) { t->center[0] = v2d->cursor[0] * aspx; t->center[1] = v2d->cursor[1] * aspy; } - + calculateCenter2D(t); } @@ -1208,7 +1210,7 @@ void calculateCenterMedian(TransInfo *t) float partial[3] = {0.0f, 0.0f, 0.0f}; int total = 0; int i; - + for(i = 0; i < t->total; i++) { if (t->data[i].flag & TD_SELECTED) { if (!(t->data[i].flag & TD_NOCENTER)) @@ -1228,7 +1230,7 @@ void calculateCenterMedian(TransInfo *t) if(i) VecMulf(partial, 1.0f / total); VECCOPY(t->center, partial); - + calculateCenter2D(t); } @@ -1258,7 +1260,7 @@ void calculateCenterBound(TransInfo *t) } VecAddf(t->center, min, max); VecMulf(t->center, 0.5); - + calculateCenter2D(t); } @@ -1294,7 +1296,7 @@ void calculateCenter(TransInfo *t) break; } /* END EDIT MODE ACTIVE ELEMENT */ #endif - + calculateCenterMedian(t); if((t->flag & (T_EDIT|T_POSE))==0) { @@ -1306,10 +1308,10 @@ void calculateCenter(TransInfo *t) projectIntView(t, t->center, t->center2d); } } - + } } - + /* setting constraint center */ VECCOPY(t->con.center, t->center); if(t->flag & (T_EDIT|T_POSE)) @@ -1317,7 +1319,7 @@ void calculateCenter(TransInfo *t) Object *ob= t->obedit?t->obedit:t->poseobj; Mat4MulVecfl(ob->obmat, t->con.center); } - + /* for panning from cameraview */ if(t->flag & T_OBJECT) { @@ -1326,21 +1328,21 @@ void calculateCenter(TransInfo *t) View3D *v3d = t->view; Scene *scene = t->scene; RegionView3D *rv3d = t->ar->regiondata; - + if(v3d->camera == OBACT && rv3d->persp==V3D_CAMOB) { float axis[3]; /* persinv is nasty, use viewinv instead, always right */ VECCOPY(axis, t->viewinv[2]); Normalize(axis); - + /* 6.0 = 6 grid units */ axis[0]= t->center[0]- 6.0f*axis[0]; axis[1]= t->center[1]- 6.0f*axis[1]; axis[2]= t->center[2]- 6.0f*axis[2]; - + projectIntView(t, axis, t->center2d); - + /* rotate only needs correct 2d center, grab needs initgrabz() value */ if(t->mode==TFM_TRANSLATION) { @@ -1350,14 +1352,14 @@ void calculateCenter(TransInfo *t) } } } - + if(t->spacetype==SPACE_VIEW3D) { /* initgrabz() defines a factor for perspective depth correction, used in window_to_3d_delta() */ if(t->flag & (T_EDIT|T_POSE)) { Object *ob= t->obedit?t->obedit:t->poseobj; float vec[3]; - + VECCOPY(vec, t->center); Mat4MulVecfl(ob->obmat, vec); initgrabz(t->ar->regiondata, vec[0], vec[1], vec[2]); @@ -1403,7 +1405,7 @@ void calculatePropRatio(TransInfo *t) /* Use rdist for falloff calculations, it is the real distance */ td->flag &= ~TD_NOACTION; dist= (t->prop_size-td->rdist)/t->prop_size; - + /* * Clamp to positive numbers. * Certain corner cases with connectivity and individual centers @@ -1411,7 +1413,7 @@ void calculatePropRatio(TransInfo *t) */ if (dist < 0.0f) dist = 0.0f; - + switch(t->prop_mode) { case PROP_SHARP: td->factor= dist*dist; @@ -1478,20 +1480,20 @@ float get_drawsize(ARegion *ar, float *co) { RegionView3D *rv3d= ar->regiondata; float size, vec[3], len1, len2; - + /* size calculus, depending ortho/persp settings, like initgrabz() */ size= rv3d->persmat[0][3]*co[0]+ rv3d->persmat[1][3]*co[1]+ rv3d->persmat[2][3]*co[2]+ rv3d->persmat[3][3]; - + VECCOPY(vec, rv3d->persinv[0]); len1= Normalize(vec); VECCOPY(vec, rv3d->persinv[1]); len2= Normalize(vec); - + size*= 0.01f*(len1>len2?len1:len2); - + /* correct for window size to make widgets appear fixed size */ if(ar->winx > ar->winy) size*= 1000.0f/(float)ar->winx; else size*= 1000.0f/(float)ar->winy; - + return size; } diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index bdf0a91bf89..19881c7bc5b 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -64,6 +64,7 @@ #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "BLI_arithb.h" #include "BLI_editVert.h" @@ -205,20 +206,22 @@ int calc_manipulator_stats(const bContext *C) if((ob->lay & v3d->lay)==0) return 0; if(obedit->type==OB_MESH) { - EditMesh *em = BKE_mesh_get_editmesh(obedit->data); - EditVert *eve; - EditSelection ese; + BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh; + BMesh *bm = em->bm; + BMVert *eve; + BMEditSelection ese; + BMIter iter; float vec[3]= {0,0,0}; /* USE LAST SELECTE WITH ACTIVE */ - if (v3d->around==V3D_ACTIVE && EM_get_actSelection(em, &ese)) { - EM_editselection_center(vec, &ese); + if (v3d->around==V3D_ACTIVE && EDBM_get_actSelection(em, &ese)) { + EDBM_editselection_center(em, vec, &ese); calc_tw_center(scene, vec); totsel= 1; } else { /* do vertices for center, and if still no normal found, use vertex normals */ - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->f & SELECT) { + BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) { + if(BM_TestHFlag(eve, BM_SELECT)) { totsel++; calc_tw_center(scene, eve->co); } diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 5173245734b..fe8e5b34b54 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -675,7 +675,7 @@ void TFM_OT_transform(struct wmOperatorType *ot) Properties_Proportional(ot); RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", ""); - + Properties_Constraints(ot); } diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index c9344b97fb2..bad744d101b 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -44,6 +44,7 @@ #include "BKE_utildefines.h" #include "BKE_armature.h" #include "BKE_context.h" +#include "BKE_tessmesh.h" #include "BKE_report.h" #include "BLI_arithb.h" @@ -77,9 +78,9 @@ void BIF_clearTransformOrientation(bContext *C) // Need to loop over all view3d if(v3d && v3d->twmode >= V3D_MANIP_CUSTOM) { v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */ - } } - +} + TransformOrientation* findOrientationName(bContext *C, char *name) { ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces; @@ -159,16 +160,16 @@ TransformOrientation *createObjectSpace(bContext *C, ReportList *reports, char * ob = base->object; - + Mat3CpyMat4(mat, ob->obmat); Mat3Ortho(mat); /* use object name if no name is given */ if (name[0] == 0) - { +{ strncpy(name, ob->id.name+2, 35); } - + return addMatrixSpace(C, mat, name, overwrite); } @@ -177,7 +178,7 @@ TransformOrientation *createBoneSpace(bContext *C, ReportList *reports, char *na float normal[3], plane[3]; getTransformOrientation(C, normal, plane, 0); - + if (createSpaceNormalTangent(mat, normal, plane) == 0) { BKE_reports_prepend(reports, "Cannot use zero-length bone"); return NULL; @@ -185,7 +186,7 @@ TransformOrientation *createBoneSpace(bContext *C, ReportList *reports, char *na if (name[0] == 0) { - strcpy(name, "Bone"); + strcpy(name, "Bone"); } return addMatrixSpace(C, mat, name, overwrite); @@ -208,7 +209,7 @@ TransformOrientation *createMeshSpace(bContext *C, ReportList *reports, char *na if (name[0] == 0) { - strcpy(name, "Vertex"); + strcpy(name, "Vertex"); } break; case ORIENTATION_EDGE: @@ -219,7 +220,7 @@ TransformOrientation *createMeshSpace(bContext *C, ReportList *reports, char *na if (name[0] == 0) { - strcpy(name, "Edge"); + strcpy(name, "Edge"); } break; case ORIENTATION_FACE: @@ -230,7 +231,7 @@ TransformOrientation *createMeshSpace(bContext *C, ReportList *reports, char *na if (name[0] == 0) { - strcpy(name, "Face"); + strcpy(name, "Face"); } break; default: @@ -296,7 +297,7 @@ TransformOrientation* addMatrixSpace(bContext *C, float mat[3][3], char name[], if (overwrite) { ts = findOrientationName(C, name); - } + } else { uniqueOrientationName(C, name); @@ -327,14 +328,14 @@ void BIF_removeTransformOrientation(bContext *C, TransformOrientation *target) { if(v3d) { int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM); - // Transform_fix_me NEED TO DO THIS FOR ALL VIEW3D + // Transform_fix_me NEED TO DO THIS FOR ALL VIEW3D if (selected_index == i) { v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */ } else if (selected_index > i) { v3d->twmode--; } - + } BLI_freelinkN(transform_spaces, ts); @@ -387,7 +388,7 @@ void BIF_selectTransformOrientation(bContext *C, TransformOrientation *target) { void BIF_selectTransformOrientationValue(bContext *C, int orientation) { View3D *v3d = CTX_wm_view3d(C); if(v3d) /* currently using generic poll */ - v3d->twmode = orientation; + v3d->twmode = orientation; } EnumPropertyItem *BIF_enumTransformOrientation(bContext *C) @@ -626,16 +627,16 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], if(ob->type==OB_MESH) { Mesh *me= ob->data; - EditMesh *em = me->edit_mesh; - EditVert *eve; - EditSelection ese; + BMEditMesh *em = me->edit_btmesh; + BMVert *eve; + BMEditSelection ese; float vec[3]= {0,0,0}; /* USE LAST SELECTED WITH ACTIVE */ - if (activeOnly && EM_get_actSelection(em, &ese)) + if (activeOnly && EDBM_get_actSelection(em, &ese)) { - EM_editselection_normal(normal, &ese); - EM_editselection_plane(plane, &ese); + EDBM_editselection_normal(normal, &ese); + EDBM_editselection_plane(em, plane, &ese); switch (ese.type) { @@ -652,30 +653,30 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], } else { - if (em->totfacesel >= 1) + if (em->bm->totfacesel >= 1) { - EditFace *efa; - - for(efa= em->faces.first; efa; efa= efa->next) - { - if(efa->f & SELECT) - { - VECADD(normal, normal, efa->n); - VecSubf(vec, efa->v2->co, efa->v1->co); + BMFace *efa; + BMIter iter; + + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if(BM_TestHFlag(efa, BM_SELECT)) { + VECADD(normal, normal, efa->no); + VecSubf(vec, efa->loopbase->v->co, + ((BMLoop*)efa->loopbase->head.next)->v->co); VECADD(plane, plane, vec); } } result = ORIENTATION_FACE; } - else if (em->totvertsel == 3) + else if (em->bm->totvertsel == 3) { - EditVert *v1 = NULL, *v2 = NULL, *v3 = NULL; + BMVert *v1 = NULL, *v2 = NULL, *v3 = NULL; + BMIter iter; float cotangent[3]; - for (eve = em->verts.first; eve; eve = eve->next) - { - if ( eve->f & SELECT ) { + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + if (BM_TestHFlag(eve, BM_SELECT)) { if (v1 == NULL) { v1 = eve; } @@ -694,12 +695,13 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], } /* if there's an edge available, use that for the tangent */ - if (em->totedgesel >= 1) + if (em->bm->totedgesel >= 1) { - EditEdge *eed = NULL; - - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f & SELECT) { + BMEdge *eed = NULL; + BMIter iter; + + BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) { + if(BM_TestHFlag(eed, BM_SELECT)) { VecSubf(plane, eed->v2->co, eed->v1->co); break; } @@ -708,12 +710,13 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], result = ORIENTATION_FACE; } - else if (em->totedgesel == 1) + else if (em->bm->totedgesel == 1) { - EditEdge *eed; - - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f & SELECT) { + BMEdge *eed = NULL; + BMIter iter; + + BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) { + if(BM_TestHFlag(eed, BM_SELECT)) { /* use average vert normals as plane and edge vector as normal */ VECCOPY(plane, eed->v1->no); VECADD(plane, plane, eed->v2->no); @@ -723,13 +726,13 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], } result = ORIENTATION_EDGE; } - else if (em->totvertsel == 2) + else if (em->bm->totvertsel == 2) { - EditVert *v1 = NULL, *v2 = NULL; - - for (eve = em->verts.first; eve; eve = eve->next) - { - if ( eve->f & SELECT ) { + BMVert *v1 = NULL, *v2 = NULL; + BMIter iter; + + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + if (BM_TestHFlag(eve, BM_SELECT)) { if (v1 == NULL) { v1 = eve; } @@ -745,24 +748,25 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], } result = ORIENTATION_EDGE; } - else if (em->totvertsel == 1) + else if (em->bm->totvertsel == 1) { - for (eve = em->verts.first; eve; eve = eve->next) - { - if ( eve->f & SELECT ) { + BMIter iter; + + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + if (BM_TestHFlag(eve, BM_SELECT)) { VECCOPY(normal, eve->no); break; } } result = ORIENTATION_VERT; } - else if (em->totvertsel > 3) + else if (em->bm->totvertsel > 3) { + BMIter iter; normal[0] = normal[1] = normal[2] = 0; - - for (eve = em->verts.first; eve; eve = eve->next) - { - if ( eve->f & SELECT ) { + + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + if (BM_TestHFlag(eve, BM_SELECT)) { VecAddf(normal, normal, eve->no); } } @@ -948,9 +952,20 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], } } - VECCOPY(normal, ob->obmat[2]); - VECCOPY(plane, ob->obmat[1]); - result = ORIENTATION_NORMAL; + if (!ob) { + normal[0] = 0.0f; + normal[1] = 0.0f; + normal[2] = 1.0f; + plane[0] = 1.0f; + plane[1] = 0.0f; + plane[2] = 0.0f; + + result = ORIENTATION_NORMAL; + } else { + VECCOPY(normal, ob->obmat[2]); + VECCOPY(plane, ob->obmat[1]); + result = ORIENTATION_NORMAL; + } } return result; diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 6cfffd1ade7..a2a7577c8d6 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -69,6 +69,8 @@ #include "BKE_object.h" #include "BKE_anim.h" /* for duplis */ #include "BKE_context.h" +#include "BKE_tessmesh.h" +#include "BKE_mesh.h" #include "ED_armature.h" #include "ED_image.h" @@ -370,9 +372,9 @@ void initSnapping(TransInfo *t, wmOperator *op) if (RNA_struct_find_property(op->ptr, "snap_project")) { t->tsnap.project = RNA_boolean_get(op->ptr, "snap_project"); - } } } + } else { snapping = ((ts->snap_flag & SCE_SNAP) == SCE_SNAP); @@ -711,8 +713,8 @@ void CalcSnapGeometry(TransInfo *t, float *vec) else { found = snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.mode); - } - + } + if (found == 1) { float tangent[3]; @@ -1176,11 +1178,11 @@ int snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm, float return retval; } -int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, EditMesh *em, float obmat[][4], float ray_start[3], float ray_normal[3], float mval[2], float *loc, float *no, int *dist, float *depth) +int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth) { int retval = 0; int totvert = dm->getNumVerts(dm); - int totface = dm->getNumFaces(dm); + int totface = dm->getNumTessFaces(dm); if (totvert > 0) { float imat[4][4]; @@ -1215,19 +1217,19 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E case SCE_SNAP_MODE_FACE: { MVert *verts = dm->getVertArray(dm); - MFace *faces = dm->getFaceArray(dm); + MFace *faces = dm->getTessFaceArray(dm); int *index_array = NULL; int index = 0; int i; if (em != NULL) { - index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX); - EM_init_index_arrays(em, 0, 0, 1); + index_array = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + EDBM_init_index_arrays(em, 0, 0, 1); } for( i = 0; i < totface; i++) { - EditFace *efa = NULL; + BMFace *efa = NULL; MFace *f = faces + i; test = 1; /* reset for every face */ @@ -1249,11 +1251,22 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E } else { - efa = EM_get_face_for_index(index); + efa = EDBM_get_face_for_index(em, index); - if (efa && (efa->h || (efa->v1->f & SELECT) || (efa->v2->f & SELECT) || (efa->v3->f & SELECT) || (efa->v4 && efa->v4->f & SELECT))) + if (efa && BM_TestHFlag(efa, BM_HIDDEN)) { test = 0; + } else if (efa) { + BMIter iter; + BMLoop *l; + + l = BMIter_New(&iter, em->bm, BM_LOOPS_OF_FACE, efa); + for ( ; l; l=BMIter_Step(&iter)) { + if (BM_TestHFlag(l->v, BM_SELECT)) { + test = 0; + break; + } + } } } } @@ -1281,7 +1294,7 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E if (em != NULL) { - EM_free_index_arrays(); + EDBM_free_index_arrays(em); } break; } @@ -1295,11 +1308,11 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E if (em != NULL) { index_array = dm->getVertDataArray(dm, CD_ORIGINDEX); - EM_init_index_arrays(em, 1, 0, 0); + EDBM_init_index_arrays(em, 1, 0, 0); } for( i = 0; i < totvert; i++) { - EditVert *eve = NULL; + BMVert *eve = NULL; MVert *v = verts + i; test = 1; /* reset for every vert */ @@ -1321,9 +1334,9 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E } else { - eve = EM_get_vert_for_index(index); + eve = EDBM_get_vert_for_index(em, index); - if (eve && (eve->h || (eve->f & SELECT))) + if (eve && (BM_TestHFlag(eve, BM_HIDDEN) || BM_TestHFlag(eve, BM_SELECT))) { test = 0; } @@ -1339,7 +1352,7 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E if (em != NULL) { - EM_free_index_arrays(); + EDBM_free_index_arrays(em); } break; } @@ -1355,11 +1368,11 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E if (em != NULL) { index_array = dm->getEdgeDataArray(dm, CD_ORIGINDEX); - EM_init_index_arrays(em, 0, 1, 0); + EDBM_init_index_arrays(em, 0, 1, 0); } for( i = 0; i < totedge; i++) { - EditEdge *eed = NULL; + BMEdge *eed = NULL; MEdge *e = edges + i; test = 1; /* reset for every vert */ @@ -1381,9 +1394,11 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E } else { - eed = EM_get_edge_for_index(index); + eed = EDBM_get_edge_for_index(em, index); - if (eed && (eed->h || (eed->v1->f & SELECT) || (eed->v2->f & SELECT))) + if (eed && (BM_TestHFlag(eed, BM_HIDDEN) || + BM_TestHFlag(eed->v1, BM_SELECT) || + BM_TestHFlag(eed->v2, BM_SELECT))) { test = 0; } @@ -1399,7 +1414,7 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E if (em != NULL) { - EM_free_index_arrays(); + EDBM_free_index_arrays(em); } break; } @@ -1416,13 +1431,13 @@ int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obma int retval = 0; if (ob->type == OB_MESH) { - EditMesh *em; + BMEditMesh *em; DerivedMesh *dm; if (editobject) { - em = ((Mesh *)ob->data)->edit_mesh; - dm = editmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH); + em = ((Mesh *)ob->data)->edit_btmesh; + dm = editbmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH); } else { @@ -1558,7 +1573,7 @@ int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta { int retval = 0; int totvert = dm->getNumVerts(dm); - int totface = dm->getNumFaces(dm); + int totface = dm->getNumTessFaces(dm); if (totvert > 0) { float imat[4][4]; @@ -1588,7 +1603,7 @@ int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta if (test == 1) { MVert *verts = dm->getVertArray(dm); - MFace *faces = dm->getFaceArray(dm); + MFace *faces = dm->getTessFaceArray(dm); int i; for( i = 0; i < totface; i++) { @@ -1684,6 +1699,7 @@ int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase Object *ob = dupli_ob->ob; if (ob->type == OB_MESH) { +#if 0 //BMESH_TODO EditMesh *em; DerivedMesh *dm = NULL; int val; @@ -1705,6 +1721,7 @@ int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase retval = retval || val; dm->release(dm); +#endif } } @@ -1712,7 +1729,7 @@ int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase } if (ob->type == OB_MESH) { - EditMesh *em; + BMEditMesh *em; DerivedMesh *dm = NULL; int val; @@ -1724,8 +1741,8 @@ int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase } else { - em = ((Mesh *)ob->data)->edit_mesh; - dm = editmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH); + em = ((Mesh *)ob->data)->edit_btmesh; + dm = editbmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH); val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels); } diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index ae1e932bb81..93760ab77e3 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -72,10 +72,10 @@ void ED_editors_exit(bContext *C) if(ob) { if(ob->type==OB_MESH) { Mesh *me= ob->data; - if(me->edit_mesh) { - free_editMesh(me->edit_mesh); - MEM_freeN(me->edit_mesh); - me->edit_mesh= NULL; + if(me->edit_btmesh) { + EDBM_FreeEditBMesh(me->edit_btmesh); + MEM_freeN(me->edit_btmesh); + me->edit_btmesh= NULL; } } else if(ob->type==OB_ARMATURE) { diff --git a/source/blender/editors/uvedit/SConscript b/source/blender/editors/uvedit/SConscript index b472b89d23d..9926eb0c7ea 100644 --- a/source/blender/editors/uvedit/SConscript +++ b/source/blender/editors/uvedit/SConscript @@ -5,6 +5,6 @@ sources = env.Glob('*.c') incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' -incs += ' ../../makesrna #/intern/opennl/extern ../../gpu' +incs += ' ../../makesrna #/intern/opennl/extern ../../gpu ../../bmesh' env.BlenderLib ( 'bf_editors_uvedit', sources, Split(incs), [], libtype=['core'], priority=[45] ) diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index fbd12007c16..f48f8441d53 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -28,6 +28,9 @@ #include <float.h> #include <math.h> #include <stdlib.h> +#include <string.h> + +#include "MEM_guardedalloc.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -41,9 +44,11 @@ #include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "BLI_arithb.h" #include "BLI_editVert.h" +#include "BLI_array.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -119,34 +124,33 @@ static int draw_uvs_face_check(Scene *scene) static void draw_uvs_shadow(SpaceImage *sima, Object *obedit) { - EditMesh *em; - EditFace *efa; - MTFace *tf; + BMEditMesh *em; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; - em= BKE_mesh_get_editmesh((Mesh*)obedit->data); + em= ((Mesh*)obedit->data)->edit_btmesh; /* draws the grey mesh when painting */ glColor3ub(112, 112, 112); - for(efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { glBegin(GL_LINE_LOOP); - glVertex2fv(tf->uv[0]); - glVertex2fv(tf->uv[1]); - glVertex2fv(tf->uv[2]); - if(efa->v4) glVertex2fv(tf->uv[3]); + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv= CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + glVertex2fv(luv->uv); + } glEnd(); } - - BKE_mesh_end_editmesh(obedit->data, em); } static int draw_uvs_dm_shadow(DerivedMesh *dm) { /* draw shadow mesh - this is the mesh with the modifier applied */ - if(dm && dm->drawUVEdges && CustomData_has_layer(&dm->faceData, CD_MTFACE)) { + if(dm && dm->drawUVEdges && CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) { glColor3ub(112, 112, 112); dm->drawUVEdges(dm); return 1; @@ -155,13 +159,19 @@ static int draw_uvs_dm_shadow(DerivedMesh *dm) return 0; } -static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFace *activetf) +static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTexPoly *activetf) { - EditFace *efa; - MTFace *tf; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; Image *ima= sima->image; - float aspx, aspy, col[4], tf_uv[4][2]; - + BLI_array_declare(tf_uv); + BLI_array_declare(tf_uvorig); + float aspx, aspy, col[4], (*tf_uv)[2] = NULL, (*tf_uvorig)[2] = NULL; + int i; + ED_space_image_uv_aspect(sima, &aspx, &aspy); switch(sima->dt_uvstretch) { @@ -169,21 +179,37 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac { float totarea=0.0f, totuvarea=0.0f, areadiff, uvarea, area; - for(efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - uv_copy_aspect(tf->uv, tf_uv, aspx, aspy); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + + BLI_array_empty(tf_uv); + BLI_array_empty(tf_uvorig); + + i = 0; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv= CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + BLI_array_growone(tf_uv); + BLI_array_growone(tf_uvorig); + + tf_uvorig[i][0] = luv->uv[0]; + tf_uvorig[i][1] = luv->uv[1]; - totarea += EM_face_area(efa); + i++; + } + + poly_copy_aspect(tf_uvorig, tf_uv, aspx, aspy, efa->len); + + totarea += BM_face_area(efa); //totuvarea += tf_area(tf, efa->v4!=0); - totuvarea += uv_area(tf_uv, efa->v4!=0); + totuvarea += poly_uv_area(tf_uv, efa->len); if(uvedit_face_visible(scene, ima, efa, tf)) { - efa->tmp.p = tf; + BMINDEX_SET(efa, 1); } else { if(tf == activetf) activetf= NULL; - efa->tmp.p = NULL; + BMINDEX_SET(efa, 0); } } @@ -191,24 +217,41 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac col[0] = 1.0; col[1] = col[2] = 0.0; glColor3fv(col); - for(efa= em->faces.first; efa; efa= efa->next) { - if((tf=(MTFace *)efa->tmp.p)) { - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); - glVertex2fv(tf->uv[0]); - glVertex2fv(tf->uv[1]); - glVertex2fv(tf->uv[2]); - if(efa->v4) glVertex2fv(tf->uv[3]); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if(BMINDEX_GET(efa)) { + glBegin(GL_POLYGON); + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + glVertex2fv(luv->uv); + } glEnd(); } } } else { - for(efa= em->faces.first; efa; efa= efa->next) { - if((tf=(MTFace *)efa->tmp.p)) { - area = EM_face_area(efa) / totarea; - uv_copy_aspect(tf->uv, tf_uv, aspx, aspy); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if(BMINDEX_GET(efa)) { + area = BM_face_area(efa) / totarea; + + BLI_array_empty(tf_uv); + BLI_array_empty(tf_uvorig); + + i = 0; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv= CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + BLI_array_growone(tf_uv); + BLI_array_growone(tf_uvorig); + + tf_uvorig[i][0] = luv->uv[0]; + tf_uvorig[i][1] = luv->uv[1]; + + i++; + } + + poly_copy_aspect(tf_uvorig, tf_uv, aspx, aspy, efa->len); + //uvarea = tf_area(tf, efa->v4!=0) / totuvarea; - uvarea = uv_area(tf_uv, efa->v4!=0) / totuvarea; + uvarea = poly_uv_area(tf_uv, efa->len) / totuvarea; if(area < FLT_EPSILON || uvarea < FLT_EPSILON) areadiff = 1.0; @@ -220,11 +263,11 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac weight_to_rgb(areadiff, col, col+1, col+2); glColor3fv(col); - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); - glVertex2fv(tf->uv[0]); - glVertex2fv(tf->uv[1]); - glVertex2fv(tf->uv[2]); - if(efa->v4) glVertex2fv(tf->uv[3]); + glBegin(GL_POLYGON); + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + glVertex2fv(luv->uv); + } glEnd(); } } @@ -233,6 +276,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac } case SI_UVDT_STRETCH_ANGLE: { +#if 0 //BMESH_TODO float uvang1,uvang2,uvang3,uvang4; float ang1,ang2,ang3,ang4; float av1[3], av2[3], av3[3], av4[3]; /* use for 2d and 3d angle vectors */ @@ -243,7 +287,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac glShadeModel(GL_SMOOTH); for(efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + tf= CustomData_em_get(&em->fdata, efa->head.data, CD_MTFACE); if(uvedit_face_visible(scene, ima, efa, tf)) { efa->tmp.p = tf; @@ -374,11 +418,13 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac glShadeModel(GL_FLAT); break; + +#endif } } } -static void draw_uvs_other(SpaceImage *sima, Scene *scene, Object *obedit, MTFace *activetf) +static void draw_uvs_other(SpaceImage *sima, Scene *scene, Object *obedit, MTexPoly *activetf) { Base *base; Image *curimage; @@ -398,17 +444,19 @@ static void draw_uvs_other(SpaceImage *sima, Scene *scene, Object *obedit, MTFac Mesh *me= ob->data; if(me->mtface) { - MFace *mface= me->mface; - MTFace *tface= me->mtface; - int a; + MPoly *mface= me->mpoly; + MTexPoly *tface= me->mtpoly; + MLoopUV *mloopuv; + int a, b; - for(a=me->totface; a>0; a--, tface++, mface++) { + for(a=me->totpoly; a>0; a--, tface++, mface++) { if(tface->tpage == curimage) { glBegin(GL_LINE_LOOP); - glVertex2fv(tface->uv[0]); - glVertex2fv(tface->uv[1]); - glVertex2fv(tface->uv[2]); - if(mface->v4) glVertex2fv(tface->uv[3]); + + mloopuv = me->mloopuv + mface->loopstart; + for (b=0; b<mface->totloop; b++, mloopuv++) { + glVertex2fv(mloopuv->uv); + } glEnd(); } } @@ -422,18 +470,22 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) { ToolSettings *ts; Mesh *me= obedit->data; - EditMesh *em; - EditFace *efa, *efa_act; - MTFace *tf, *activetf = NULL; + BMEditMesh *em; + BMFace *efa, *efa_act, *activef; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf, *activetf = NULL; + MLoopUV *luv; DerivedMesh *finaldm, *cagedm; char col1[4], col2[4]; float pointsize; int drawfaces, interpedges, lastsel, sel; + int i; Image *ima= sima->image; - em= BKE_mesh_get_editmesh(me); - activetf= EM_get_active_mtface(em, &efa_act, NULL, 0); /* will be set to NULL if hidden */ - + em= me->edit_btmesh; + activetf= EDBM_get_active_mtexpoly(em, &efa_act, 0); /* will be set to NULL if hidden */ + activef = EDBM_get_actFace(em, 0); ts= scene->toolsettings; drawfaces= draw_uvs_face_check(scene); @@ -452,7 +504,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) /* first try existing derivedmesh */ if(!draw_uvs_dm_shadow(em->derivedFinal)) { /* create one if it does not exist */ - cagedm = editmesh_get_derived_cage_and_final(scene, obedit, em, &finaldm, CD_MASK_BAREMESH|CD_MASK_MTFACE); + cagedm = editbmesh_get_derived_cage_and_final(scene, obedit, me->edit_btmesh, &finaldm, CD_MASK_BAREMESH|CD_MASK_MTFACE); /* when sync selection is enabled, all faces are drawn (except for hidden) * so if cage is the same as the final, theres no point in drawing this */ @@ -477,45 +529,46 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - for(efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); if(uvedit_face_visible(scene, ima, efa, tf)) { - efa->tmp.p = tf; - if(tf==activetf) continue; /* important the temp pointer is set above */ + BMINDEX_SET(efa, 1); + if(tf==activetf) continue; /* important the temp boolean is set above */ - if(uvedit_face_selected(scene, efa, tf)) + if(uvedit_face_selected(scene, em, efa)) glColor4ubv((GLubyte *)col2); else glColor4ubv((GLubyte *)col1); - - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); - glVertex2fv(tf->uv[0]); - glVertex2fv(tf->uv[1]); - glVertex2fv(tf->uv[2]); - if(efa->v4) glVertex2fv(tf->uv[3]); + + glBegin(GL_POLYGON); + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + glVertex2fv(luv->uv); + } glEnd(); } else { if(tf == activetf) activetf= NULL; - efa->tmp.p = NULL; + BMINDEX_SET(efa, 0); } } glDisable(GL_BLEND); } else { /* would be nice to do this within a draw loop but most below are optional, so it would involve too many checks */ - for(efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); if(uvedit_face_visible(scene, ima, efa, tf)) { - efa->tmp.p = tf; + BMINDEX_SET(efa, 1); } else { if(tf == activetf) activetf= NULL; - efa->tmp.p = NULL; + BMINDEX_SET(efa, 0); } } @@ -523,7 +576,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) /* 3. draw active face stippled */ - if(activetf) { + if(activef) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); UI_ThemeColor4(TH_EDITMESH_ACTIVE); @@ -531,11 +584,11 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glEnable(GL_POLYGON_STIPPLE); glPolygonStipple(stipple_quarttone); - glBegin(efa_act->v4? GL_QUADS: GL_TRIANGLES); - glVertex2fv(activetf->uv[0]); - glVertex2fv(activetf->uv[1]); - glVertex2fv(activetf->uv[2]); - if(efa_act->v4) glVertex2fv(activetf->uv[3]); + glBegin(GL_POLYGON); + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, activef) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + glVertex2fv(luv->uv); + } glEnd(); glDisable(GL_POLYGON_STIPPLE); @@ -552,39 +605,38 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) switch(sima->dt_uv) { case SI_UVDT_DASH: - for(efa= em->faces.first; efa; efa= efa->next) { - tf= (MTFace *)efa->tmp.p; /* visible faces cached */ + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BMINDEX_GET(efa)) + continue; + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); if(tf) { cpack(0x111111); glBegin(GL_LINE_LOOP); - glVertex2fv(tf->uv[0]); - glVertex2fv(tf->uv[1]); - glVertex2fv(tf->uv[2]); - if(efa->v4) glVertex2fv(tf->uv[3]); + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + glVertex2fv(luv->uv); + } glEnd(); - + setlinestyle(2); cpack(0x909090); - glBegin(GL_LINE_STRIP); - glVertex2fv(tf->uv[0]); - glVertex2fv(tf->uv[1]); - glEnd(); - - glBegin(GL_LINE_STRIP); - glVertex2fv(tf->uv[0]); - if(efa->v4) glVertex2fv(tf->uv[3]); - else glVertex2fv(tf->uv[2]); - glEnd(); - - glBegin(GL_LINE_STRIP); - glVertex2fv(tf->uv[1]); - glVertex2fv(tf->uv[2]); - if(efa->v4) glVertex2fv(tf->uv[3]); + glBegin(GL_LINE_LOOP); + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + glVertex2fv(luv->uv); + } glEnd(); + /*glBegin(GL_LINE_STRIP); + luv = CustomData_bmesh_get(&em->bm->ldata, efa->loopbase->head.data, CD_MLOOPUV); + glVertex2fv(luv->uv); + luv = CustomData_bmesh_get(&em->bm->ldata, efa->loopbase->head.next->data, CD_MLOOPUV); + glVertex2fv(luv->uv); + glEnd();*/ + setlinestyle(0); } } @@ -594,34 +646,32 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) if(sima->dt_uv==SI_UVDT_WHITE) glColor3f(1.0f, 1.0f, 1.0f); else glColor3f(0.0f, 0.0f, 0.0f); - for(efa= em->faces.first; efa; efa= efa->next) { - tf= (MTFace *)efa->tmp.p; /* visible faces cached */ + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BMINDEX_GET(efa)) + continue; - if(tf) { - glBegin(GL_LINE_LOOP); - glVertex2fv(tf->uv[0]); - glVertex2fv(tf->uv[1]); - glVertex2fv(tf->uv[2]); - if(efa->v4) glVertex2fv(tf->uv[3]); - glEnd(); + glBegin(GL_LINE_LOOP); + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + glVertex2fv(luv->uv); } + glEnd(); } break; case SI_UVDT_OUTLINE: glLineWidth(3); cpack(0x0); - for(efa= em->faces.first; efa; efa= efa->next) { - tf= (MTFace *)efa->tmp.p; /* visible faces cached */ - - if(tf) { - glBegin(GL_LINE_LOOP); - glVertex2fv(tf->uv[0]); - glVertex2fv(tf->uv[1]); - glVertex2fv(tf->uv[2]); - if(efa->v4) glVertex2fv(tf->uv[3]); - glEnd(); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BMINDEX_GET(efa)) + continue; + + glBegin(GL_LINE_LOOP); + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + glVertex2fv(luv->uv); } + glEnd(); } glLineWidth(1); @@ -635,83 +685,60 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) if(interpedges) { glShadeModel(GL_SMOOTH); - for(efa= em->faces.first; efa; efa= efa->next) { - tf= (MTFace *)efa->tmp.p; /* visible faces cached */ + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BMINDEX_GET(efa)) + continue; - if(tf) { - glBegin(GL_LINE_LOOP); - sel = (uvedit_uv_selected(scene, efa, tf, 0)? 1 : 0); - if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } - glVertex2fv(tf->uv[0]); - - sel = uvedit_uv_selected(scene, efa, tf, 1)? 1 : 0; - if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } - glVertex2fv(tf->uv[1]); - - sel = uvedit_uv_selected(scene, efa, tf, 2)? 1 : 0; + glBegin(GL_LINE_LOOP); + i = 0; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + sel = (uvedit_uv_selected(em, scene, l)? 1 : 0); if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } - glVertex2fv(tf->uv[2]); - - if(efa->v4) { - sel = uvedit_uv_selected(scene, efa, tf, 3)? 1 : 0; - if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } - glVertex2fv(tf->uv[3]); - } - - glEnd(); + + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + glVertex2fv(luv->uv); + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.next->data, CD_MLOOPUV); + glVertex2fv(luv->uv); + i += 1; } + glEnd(); } glShadeModel(GL_FLAT); } else { - for(efa= em->faces.first; efa; efa= efa->next) { - tf= (MTFace *)efa->tmp.p; /* visible faces cached */ + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BMINDEX_GET(efa)) + continue; - if(tf) { - glBegin(GL_LINES); - sel = (uvedit_edge_selected(scene, efa, tf, 0)? 1 : 0); - if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } - glVertex2fv(tf->uv[0]); - glVertex2fv(tf->uv[1]); - - sel = uvedit_edge_selected(scene, efa, tf, 1)? 1 : 0; - if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } - glVertex2fv(tf->uv[1]); - glVertex2fv(tf->uv[2]); - - sel = uvedit_edge_selected(scene, efa, tf, 2)? 1 : 0; + glBegin(GL_LINE_LOOP); + i = 0; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + sel = (uvedit_edge_selected(em, scene, l)? 1 : 0); if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } - glVertex2fv(tf->uv[2]); - - if(efa->v4) { - glVertex2fv(tf->uv[3]); - - sel = uvedit_edge_selected(scene, efa, tf, 3)? 1 : 0; - if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } - glVertex2fv(tf->uv[3]); - } - - glVertex2fv(tf->uv[0]); - - glEnd(); + + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + glVertex2fv(luv->uv); + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.next->data, CD_MLOOPUV); + glVertex2fv(luv->uv); + i += 1; } + glEnd(); } } } else { /* no nice edges */ - for(efa= em->faces.first; efa; efa= efa->next) { - tf= (MTFace *)efa->tmp.p; /* visible faces cached */ - - if(tf) { - glBegin(GL_LINE_LOOP); - glVertex2fv(tf->uv[0]); - glVertex2fv(tf->uv[1]); - glVertex2fv(tf->uv[2]); - if(efa->v4) glVertex2fv(tf->uv[3]); - glEnd(); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BMINDEX_GET(efa)) + continue; + + glBegin(GL_LINE_LOOP); + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + glVertex2fv(luv->uv); } + glEnd(); } } @@ -735,11 +762,12 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) UI_ThemeColor(TH_WIRE); bglBegin(GL_POINTS); - for(efa= em->faces.first; efa; efa= efa->next) { - tf= (MTFace *)efa->tmp.p; /* visible faces cached */ + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BMINDEX_GET(efa)) + continue; - if(tf && !uvedit_face_selected(scene, efa, tf)) { - uv_center(tf->uv, cent, efa->v4 != NULL); + if(!uvedit_face_selected(scene, em, efa)) { + poly_uv_center(em, efa, cent); bglVertex2fv(cent); } } @@ -749,11 +777,12 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) UI_ThemeColor(TH_FACE_DOT); bglBegin(GL_POINTS); - for(efa= em->faces.first; efa; efa= efa->next) { - tf= (MTFace *)efa->tmp.p; /* visible faces cached */ + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BMINDEX_GET(efa)) + continue; - if(tf && uvedit_face_selected(scene, efa, tf)) { - uv_center(tf->uv, cent, efa->v4 != NULL); + if(uvedit_face_selected(scene, em, efa)) { + poly_uv_center(em, efa, cent); bglVertex2fv(cent); } } @@ -769,18 +798,14 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glPointSize(pointsize); bglBegin(GL_POINTS); - for(efa= em->faces.first; efa; efa= efa->next) { - tf= (MTFace *)efa->tmp.p; /* visible faces cached */ - - if(tf) { - if(!uvedit_uv_selected(scene, efa, tf, 0)) - bglVertex2fv(tf->uv[0]); - if(!uvedit_uv_selected(scene, efa, tf, 1)) - bglVertex2fv(tf->uv[1]); - if(!uvedit_uv_selected(scene, efa, tf, 2)) - bglVertex2fv(tf->uv[2]); - if(efa->v4 && !uvedit_uv_selected(scene, efa, tf, 3)) - bglVertex2fv(tf->uv[3]); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BMINDEX_GET(efa)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + if(!uvedit_uv_selected(em, scene, l)) + bglVertex2fv(luv->uv); } } bglEnd(); @@ -791,46 +816,39 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) cpack(0xFF); bglBegin(GL_POINTS); - for(efa= em->faces.first; efa; efa= efa->next) { - tf= (MTFace *)efa->tmp.p; /* visible faces cached */ - - if(tf) { - if(tf->unwrap & TF_PIN1) - bglVertex2fv(tf->uv[0]); - if(tf->unwrap & TF_PIN2) - bglVertex2fv(tf->uv[1]); - if(tf->unwrap & TF_PIN3) - bglVertex2fv(tf->uv[2]); - if(efa->v4 && (tf->unwrap & TF_PIN4)) - bglVertex2fv(tf->uv[3]); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BMINDEX_GET(efa)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + if(luv->flag & MLOOPUV_PINNED) + bglVertex2fv(luv->uv); } } bglEnd(); /* selected uvs */ UI_ThemeColor(TH_VERTEX_SELECT); - glPointSize(pointsize); + glPointSize(pointsize); bglBegin(GL_POINTS); - for(efa= em->faces.first; efa; efa= efa->next) { - tf= (MTFace *)efa->tmp.p; /* visible faces cached */ - - if(tf) { - if(uvedit_uv_selected(scene, efa, tf, 0)) - bglVertex2fv(tf->uv[0]); - if(uvedit_uv_selected(scene, efa, tf, 1)) - bglVertex2fv(tf->uv[1]); - if(uvedit_uv_selected(scene, efa, tf, 2)) - bglVertex2fv(tf->uv[2]); - if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) - bglVertex2fv(tf->uv[3]); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BMINDEX_GET(efa)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + if(uvedit_uv_selected(em, scene, l)) + bglVertex2fv(luv->uv); } } bglEnd(); } glPointSize(1.0); - BKE_mesh_end_editmesh(obedit->data, em); } void draw_uvedit_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedit) diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index cca357c8685..a203fc9b55b 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -30,12 +30,16 @@ #define ED_UVEDIT_INTERN_H struct SpaceImage; -struct EditFace; -struct MTFace; +struct MTexPoly; struct Scene; struct Image; struct Object; struct wmOperatorType; +struct BMEditMesh; +struct BMFace; +struct BMLoop; +struct BMEdge; +struct BMVert; #define UV_SELECT_ALL 1 #define UV_SELECT_PINNED 2 @@ -45,26 +49,28 @@ struct wmOperatorType; #define TF_SEL_MASK(id) (TF_SEL1 << id) /* visibility and selection */ -int uvedit_face_visible_nolocal(struct Scene *scene, struct EditFace *efa); -int uvedit_face_visible(struct Scene *scene, struct Image *ima, struct EditFace *efa, struct MTFace *tf); +int uvedit_face_visible_nolocal(struct Scene *scene, struct BMFace *efa); -int uvedit_face_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf); -void uvedit_face_select(struct Scene *scene, struct EditFace *efa, struct MTFace *tf); -void uvedit_face_deselect(struct Scene *scene, struct EditFace *efa, struct MTFace *tf); +/*all the uvedit_xxxx_[de]selected functions are + declared in ED_uvedit.h*/ +int uvedit_face_select(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa); +int uvedit_face_deselect(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa); -int uvedit_edge_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i); -void uvedit_edge_select(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i); -void uvedit_edge_deselect(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i); +void uvedit_edge_select(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l); +void uvedit_edge_deselect(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l); -int uvedit_uv_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i); -void uvedit_uv_select(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i); -void uvedit_uv_deselect(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i); +void uvedit_uv_select(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l); +void uvedit_uv_deselect(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l); /* geometric utilities */ void uv_center(float uv[][2], float cent[2], int quad); float uv_area(float uv[][2], int quad); void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy); +float poly_uv_area(float uv[][2], int len); +void poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len); +void poly_uv_center(struct BMEditMesh *em, struct BMFace *f, float cent[2]); + /* operators */ void UV_OT_average_islands_scale(struct wmOperatorType *ot); void UV_OT_cube_project(struct wmOperatorType *ot); diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 1641d1c8fac..df418e60254 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -30,12 +30,14 @@ #include <stdlib.h> #include <string.h> #include <math.h> +#include <string.h> #include "MEM_guardedalloc.h" #include "DNA_object_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_image_types.h" #include "DNA_space_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -44,6 +46,7 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_editVert.h" +#include "BLI_array.h" #include "BKE_context.h" #include "BKE_customdata.h" @@ -53,6 +56,7 @@ #include "BKE_mesh.h" #include "BKE_report.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "ED_image.h" #include "ED_mesh.h" @@ -71,19 +75,20 @@ #include "uvedit_intern.h" +#define EFA_F1_FLAG 2 + /************************* state testing ************************/ int ED_uvedit_test(Object *obedit) { - EditMesh *em; + BMEditMesh *em; int ret; - if(!obedit || obedit->type != OB_MESH) + if(obedit->type != OB_MESH) return 0; - em = BKE_mesh_get_editmesh(obedit->data); - ret = EM_texFaceCheck(em); - BKE_mesh_end_editmesh(obedit->data, em); + em = ((Mesh*)obedit->data)->edit_btmesh; + ret = EDBM_texFaceCheck(em); return ret; } @@ -92,9 +97,10 @@ int ED_uvedit_test(Object *obedit) void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *previma) { - EditMesh *em; - EditFace *efa; - MTFace *tf; + BMEditMesh *em; + BMFace *efa; + BMIter iter; + MTexPoly *tf; int update= 0; /* skip assigning these procedural images... */ @@ -105,21 +111,21 @@ void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *pre if(!obedit || (obedit->type != OB_MESH)) return; - em= BKE_mesh_get_editmesh(((Mesh*)obedit->data)); - if(!em || !em->faces.first) { - BKE_mesh_end_editmesh(obedit->data, em); + em= ((Mesh*)obedit->data)->edit_btmesh; + if(!em || !em->bm->totface) { return; } /* ensure we have a uv layer */ - if(!CustomData_has_layer(&em->fdata, CD_MTFACE)) { - EM_add_data_layer(em, &em->fdata, CD_MTFACE); + if(!CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY)) { + BM_add_data_layer(em->bm, &em->bm->pdata, CD_MTEXPOLY); + BM_add_data_layer(em->bm, &em->bm->ldata, CD_MLOOPUV); update= 1; } /* now assign to all visible faces */ - for(efa= em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); if(uvedit_face_visible(scene, previma, efa, tf)) { if(ima) { @@ -141,17 +147,16 @@ void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *pre /* and update depdency graph */ if(update) DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - - BKE_mesh_end_editmesh(obedit->data, em); } /* dotile - 1, set the tile flag (from the space image) * 2, set the tile index for the faces. */ void ED_uvedit_set_tile(bContext *C, Scene *scene, Object *obedit, Image *ima, int curtile) { - EditMesh *em; - EditFace *efa; - MTFace *tf; + BMEditMesh *em; + BMFace *efa; + BMIter iter; + MTexPoly *tf; /* verify if we have something to do */ if(!ima || !ED_uvedit_test(obedit)) @@ -161,18 +166,17 @@ void ED_uvedit_set_tile(bContext *C, Scene *scene, Object *obedit, Image *ima, i if(ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE) return; - em= BKE_mesh_get_editmesh((Mesh*)obedit->data); + em= ((Mesh*)obedit->data)->edit_btmesh; - for(efa= em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - if(efa->h==0 && efa->f & SELECT) + if(!BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT)) tf->tile= curtile; /* set tile index */ } DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); } /*********************** space conversion *********************/ @@ -181,13 +185,7 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist { int width, height; - if(sima) { - ED_space_image_size(sima, &width, &height); - } - else { - width= 256; - height= 256; - } + ED_space_image_size(sima, &width, &height); dist[0]= pixeldist/width; dist[1]= pixeldist/height; @@ -195,18 +193,17 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist /*************** visibility and selection utilities **************/ -int uvedit_face_visible_nolocal(Scene *scene, EditFace *efa) +int uvedit_face_visible_nolocal(Scene *scene, BMFace *efa) { ToolSettings *ts= scene->toolsettings; if(ts->uv_flag & UV_SYNC_SELECTION) - return (efa->h==0); + return (BM_TestHFlag(efa, BM_HIDDEN)==0); else - return (efa->h==0 && (efa->f & SELECT)); + return (BM_TestHFlag(efa, BM_HIDDEN)==0 && BM_TestHFlag(efa, BM_SELECT)); } -int uvedit_face_visible(Scene *scene, Image *ima, EditFace *efa, MTFace *tf) -{ +int uvedit_face_visible(Scene *scene, Image *ima, BMFace *efa, MTexPoly *tf) { ToolSettings *ts= scene->toolsettings; if(ts->uv_flag & UV_SHOW_SAME_IMAGE) @@ -215,134 +212,216 @@ int uvedit_face_visible(Scene *scene, Image *ima, EditFace *efa, MTFace *tf) return uvedit_face_visible_nolocal(scene, efa); } -int uvedit_face_selected(Scene *scene, EditFace *efa, MTFace *tf) +int uvedit_face_selected(Scene *scene, BMEditMesh *em, BMFace *efa) { ToolSettings *ts= scene->toolsettings; if(ts->uv_flag & UV_SYNC_SELECTION) - return (efa->f & SELECT); - else - return (!(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) &&(!efa->v4 || tf->flag & TF_SEL4)); + return (BM_TestHFlag(efa, BM_SELECT)); + else { + BMLoop *l; + MLoopUV *luv; + BMIter liter; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + if (!(luv->flag & MLOOPUV_VERTSEL)) + return 0; + } + + return 1; + } } -void uvedit_face_select(Scene *scene, EditFace *efa, MTFace *tf) +int uvedit_face_select(Scene *scene, BMEditMesh *em, BMFace *efa) { ToolSettings *ts= scene->toolsettings; if(ts->uv_flag & UV_SYNC_SELECTION) - EM_select_face(efa, 1); - else - tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); + BM_Select(em->bm, efa, 1); + else { + BMLoop *l; + MLoopUV *luv; + BMIter liter; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv->flag |= MLOOPUV_VERTSEL; + } + + return 1; + } + + return 0; } -void uvedit_face_deselect(Scene *scene, EditFace *efa, MTFace *tf) +int uvedit_face_deselect(Scene *scene, BMEditMesh *em, BMFace *efa) { ToolSettings *ts= scene->toolsettings; if(ts->uv_flag & UV_SYNC_SELECTION) - EM_select_face(efa, 0); - else - tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); + BM_Select(em->bm, efa, 0); + else { + BMLoop *l; + MLoopUV *luv; + BMIter liter; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv->flag &= ~MLOOPUV_VERTSEL; + } + + return 1; + } + + return 0; } -int uvedit_edge_selected(Scene *scene, EditFace *efa, MTFace *tf, int i) +int uvedit_edge_selected(BMEditMesh *em, Scene *scene, BMLoop *l) { ToolSettings *ts= scene->toolsettings; - int nvert= (efa->v4)? 4: 3; if(ts->uv_flag & UV_SYNC_SELECTION) { if(ts->selectmode == SCE_SELECT_FACE) - return (efa->f & SELECT); - else if(ts->selectmode == SCE_SELECT_EDGE) - return (*(&efa->e1 + i))->f & SELECT; - else - return (((efa->v1 + i)->f & SELECT) && ((efa->v1 + (i+1)%nvert)->f & SELECT)); + return BM_TestHFlag(l->f, BM_SELECT); + else if(ts->selectmode == SCE_SELECT_EDGE) { + return BM_TestHFlag(l->e, BM_SELECT); + } else + return BM_TestHFlag(l->v, BM_SELECT) && + BM_TestHFlag(((BMLoop*)l->head.next)->v, BM_SELECT); + } + else { + MLoopUV *luv1, *luv2; + + luv1 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv2 = CustomData_bmesh_get(&em->bm->ldata, l->head.next->data, CD_MLOOPUV); + + return (luv1->flag & MLOOPUV_VERTSEL) && (luv2->flag & MLOOPUV_VERTSEL); } - else - return (tf->flag & TF_SEL_MASK(i)) && (tf->flag & TF_SEL_MASK((i+1)%nvert)); } -void uvedit_edge_select(Scene *scene, EditFace *efa, MTFace *tf, int i) +void uvedit_edge_select(BMEditMesh *em, Scene *scene, BMLoop *l) + { ToolSettings *ts= scene->toolsettings; - int nvert= (efa->v4)? 4: 3; if(ts->uv_flag & UV_SYNC_SELECTION) { if(ts->selectmode == SCE_SELECT_FACE) - EM_select_face(efa, 1); + BM_Select(em->bm, l->f, 1); else if(ts->selectmode == SCE_SELECT_EDGE) - EM_select_edge((*(&efa->e1 + i)), 1); + BM_Select(em->bm, l->e, 1); else { - (efa->v1 + i)->f |= SELECT; - (efa->v1 + (i+1)%nvert)->f |= SELECT; + BM_Select(em->bm, l->e->v1, 1); + BM_Select(em->bm, l->e->v2, 1); } } - else - tf->flag |= TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert); + else { + MLoopUV *luv1, *luv2; + + luv1 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv2 = CustomData_bmesh_get(&em->bm->ldata, l->head.next->data, CD_MLOOPUV); + + luv1->flag |= MLOOPUV_VERTSEL; + luv2->flag |= MLOOPUV_VERTSEL; + } } -void uvedit_edge_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i) +void uvedit_edge_deselect(BMEditMesh *em, Scene *scene, BMLoop *l) + { ToolSettings *ts= scene->toolsettings; - int nvert= (efa->v4)? 4: 3; if(ts->uv_flag & UV_SYNC_SELECTION) { if(ts->selectmode == SCE_SELECT_FACE) - EM_select_face(efa, 0); + BM_Select(em->bm, l->f, 0); else if(ts->selectmode == SCE_SELECT_EDGE) - EM_select_edge((*(&efa->e1 + i)), 0); + BM_Select(em->bm, l->e, 0); else { - (efa->v1 + i)->f &= ~SELECT; - (efa->v1 + (i+1)%nvert)->f &= ~SELECT; + BM_Select(em->bm, l->e->v1, 0); + BM_Select(em->bm, l->e->v2, 0); } } - else - tf->flag &= ~(TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert)); + else { + MLoopUV *luv1, *luv2; + + luv1 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv2 = CustomData_bmesh_get(&em->bm->ldata, l->head.next->data, CD_MLOOPUV); + + luv1->flag &= ~MLOOPUV_VERTSEL; + luv2->flag &= ~MLOOPUV_VERTSEL; + } } -int uvedit_uv_selected(Scene *scene, EditFace *efa, MTFace *tf, int i) +int uvedit_uv_selected(BMEditMesh *em, Scene *scene, BMLoop *l) { ToolSettings *ts= scene->toolsettings; if(ts->uv_flag & UV_SYNC_SELECTION) { if(ts->selectmode == SCE_SELECT_FACE) - return (efa->f & SELECT); + return BM_TestHFlag(l->f, BM_SELECT); else - return (*(&efa->v1 + i))->f & SELECT; + return BM_TestHFlag(l, BM_SELECT); + } + else { + MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + return luv->flag & MLOOPUV_VERTSEL; } - else - return tf->flag & TF_SEL_MASK(i); } -void uvedit_uv_select(Scene *scene, EditFace *efa, MTFace *tf, int i) +void uvedit_uv_select(BMEditMesh *em, Scene *scene, BMLoop *l) { ToolSettings *ts= scene->toolsettings; if(ts->uv_flag & UV_SYNC_SELECTION) { if(ts->selectmode == SCE_SELECT_FACE) - EM_select_face(efa, 1); + BM_Select(em->bm, l->f, 1); else - (*(&efa->v1 + i))->f |= SELECT; + BM_Select(em->bm, l->v, 1); + } + else { + MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + luv->flag |= MLOOPUV_VERTSEL; } - else - tf->flag |= TF_SEL_MASK(i); } -void uvedit_uv_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i) +void uvedit_uv_deselect(BMEditMesh *em, Scene *scene, BMLoop *l) { ToolSettings *ts= scene->toolsettings; if(ts->uv_flag & UV_SYNC_SELECTION) { if(ts->selectmode == SCE_SELECT_FACE) - EM_select_face(efa, 0); + BM_Select(em->bm, l->f, 0); else - (*(&efa->v1 + i))->f &= ~SELECT; + BM_Select(em->bm, l->v, 0); + } + else { + MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + luv->flag &= ~MLOOPUV_VERTSEL; } - else - tf->flag &= ~TF_SEL_MASK(i); } /*********************** geometric utilities ***********************/ +void poly_uv_center(BMEditMesh *em, BMFace *f, float cent[2]) +{ + BMLoop *l; + MLoopUV *luv; + BMIter liter; + + cent[0] = cent[1] = 0.0f; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + cent[0] += luv->uv[0]; + cent[1] += luv->uv[1]; + } + + cent[0] /= (float) f->len; + cent[1] /= (float) f->len; +} + void uv_center(float uv[][2], float cent[2], int quad) { @@ -364,6 +443,28 @@ float uv_area(float uv[][2], int quad) return AreaF2Dfl(uv[0], uv[1], uv[2]); } +float poly_uv_area(float uv[][2], int len) +{ + //BMESH_TODO: make this not suck + //maybe use scanfill? I dunno. + + if(len >= 4) + return AreaF2Dfl(uv[0], uv[1], uv[2]) + AreaF2Dfl(uv[0], uv[2], uv[3]); + else + return AreaF2Dfl(uv[0], uv[1], uv[2]); + + return 1.0; +} + +void poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len) +{ + int i; + for (i=0; i<len; i++) { + uv[i][0] = uv_orig[i][0]*aspx; + uv[i][1] = uv_orig[i][1]*aspy; + } +} + void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy) { uv[0][0] = uv_orig[0][0]*aspx; @@ -381,33 +482,42 @@ void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy) int ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float *min, float *max) { - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); - EditFace *efa; - MTFace *tf; + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; int sel; INIT_MINMAX2(min, max); sel= 0; - for(efa= em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(uvedit_face_visible(scene, ima, efa, tf)) { - if(uvedit_uv_selected(scene, efa, tf, 0)) { DO_MINMAX2(tf->uv[0], min, max); sel = 1; } - if(uvedit_uv_selected(scene, efa, tf, 1)) { DO_MINMAX2(tf->uv[1], min, max); sel = 1; } - if(uvedit_uv_selected(scene, efa, tf, 2)) { DO_MINMAX2(tf->uv[2], min, max); sel = 1; } - if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3))) { DO_MINMAX2(tf->uv[3], min, max); sel = 1; } - } + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if (uvedit_uv_selected(em, scene, l)) + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + DO_MINMAX2(luv->uv, min, max); + sel = 1; + } } - - BKE_mesh_end_editmesh(obedit->data, em); + return sel; } -int uvedit_center(Scene *scene, Image *ima, Object *obedit, float *cent, int mode) +int uvedit_center(Scene *scene, Image *ima, Object *obedit, + float *cent, int mode) { - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); - EditFace *efa; - MTFace *tf; + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; float min[2], max[2]; int change= 0; @@ -418,14 +528,18 @@ int uvedit_center(Scene *scene, Image *ima, Object *obedit, float *cent, int mod else if(mode==1) { INIT_MINMAX2(min, max); - for(efa= em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - if(uvedit_face_visible(scene, ima, efa, tf)) { - if(uvedit_uv_selected(scene, efa, tf, 0)) { DO_MINMAX2(tf->uv[0], min, max); change= 1;} - if(uvedit_uv_selected(scene, efa, tf, 1)) { DO_MINMAX2(tf->uv[1], min, max); change= 1;} - if(uvedit_uv_selected(scene, efa, tf, 2)) { DO_MINMAX2(tf->uv[2], min, max); change= 1;} - if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3))) { DO_MINMAX2(tf->uv[3], min, max); change= 1;} + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if (uvedit_uv_selected(em, scene, l)) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + DO_MINMAX2(luv->uv, min, max); + change= 1; + } } } } @@ -434,108 +548,147 @@ int uvedit_center(Scene *scene, Image *ima, Object *obedit, float *cent, int mod cent[0]= (min[0]+max[0])/2.0; cent[1]= (min[1]+max[1])/2.0; - BKE_mesh_end_editmesh(obedit->data, em); return 1; } - BKE_mesh_end_editmesh(obedit->data, em); return 0; } /************************** find nearest ****************************/ typedef struct NearestHit { - EditFace *efa; - MTFace *tf; - - int vert, uv; - int edge, vert2; + BMFace *efa; + MTexPoly *tf; + BMLoop *l, *nextl; + MLoopUV *luv, *nextluv; + int lindex; //index of loop within face + int vert1, vert2; //index in mesh of edge vertices } NearestHit; -static void find_nearest_uv_edge(Scene *scene, Image *ima, EditMesh *em, float co[2], NearestHit *hit) +static void find_nearest_uv_edge(Scene *scene, Image *ima, BMEditMesh *em, float co[2], NearestHit *hit) { - MTFace *tf; - EditFace *efa; - EditVert *eve; + MTexPoly *tf; + BMFace *efa; + BMLoop *l; + BMVert *eve; + BMIter iter, liter; + MLoopUV *luv, *nextluv; float mindist, dist; - int i, nverts; + int i; mindist= 1e10f; memset(hit, 0, sizeof(*hit)); - for(i=0, eve=em->verts.first; eve; eve=eve->next, i++) - eve->tmp.l = i; + eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) { + BMINDEX_SET(eve, i); + } - for(efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - if(uvedit_face_visible(scene, ima, efa, tf)) { - nverts= efa->v4? 4: 3; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + i = 0; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + nextluv = CustomData_bmesh_get(&em->bm->ldata, l->head.next->data, CD_MLOOPUV); - for(i=0; i<nverts; i++) { - dist= PdistVL2Dfl(co, tf->uv[i], tf->uv[(i+1)%nverts]); + dist= PdistVL2Dfl(co, luv->uv, nextluv->uv); - if(dist < mindist) { - hit->tf= tf; - hit->efa= efa; - hit->edge= i; - mindist= dist; + if(dist < mindist) { + hit->tf= tf; + hit->efa= efa; + + hit->l = l; + hit->nextl = (BMLoop*)l->head.next; + hit->luv = luv; + hit->nextluv = nextluv; + hit->lindex = i; + hit->vert1 = BMINDEX_GET(hit->l->v); + hit->vert2 = BMINDEX_GET(((BMLoop*)hit->l->head.next)->v); - hit->vert= (*(&efa->v1 + i))->tmp.l; - hit->vert2= (*(&efa->v1 + ((i+1)%nverts)))->tmp.l; - } + mindist = dist; } + + i++; } } } -static void find_nearest_uv_face(Scene *scene, Image *ima, EditMesh *em, float co[2], NearestHit *hit) +static void find_nearest_uv_face(Scene *scene, Image *ima, BMEditMesh *em, float co[2], NearestHit *hit) { - MTFace *tf; - EditFace *efa; + MTexPoly *tf; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; float mindist, dist, cent[2]; - int i, nverts; mindist= 1e10f; memset(hit, 0, sizeof(*hit)); - - for(efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(uvedit_face_visible(scene, ima, efa, tf)) { - nverts= efa->v4? 4: 3; - cent[0]= cent[1]= 0.0f; + /*this will fill in hit.vert1 and hit.vert2*/ + find_nearest_uv_edge(scene, ima, em, co, hit); + hit->l = hit->nextl = NULL; + hit->luv = hit->nextluv = NULL; - for(i=0; i<nverts; i++) { - cent[0] += tf->uv[i][0]; - cent[1] += tf->uv[i][1]; - } + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + cent[0]= cent[1]= 0.0f; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - cent[0] /= nverts; - cent[1] /= nverts; - dist= fabs(co[0]- cent[0]) + fabs(co[1]- cent[1]); + cent[0] += luv->uv[0]; + cent[1] += luv->uv[1]; + } - if(dist < mindist) { - hit->tf= tf; - hit->efa= efa; - mindist= dist; - } + cent[0] /= efa->len; + cent[1] /= efa->len; + dist= fabs(co[0]- cent[0]) + fabs(co[1]- cent[1]); + + if(dist < mindist) { + hit->tf= tf; + hit->efa= efa; + mindist= dist; } } } -static int nearest_uv_between(MTFace *tf, int nverts, int id, float co[2], float uv[2]) +static int nearest_uv_between(BMEditMesh *em, BMFace *efa, int nverts, int id, + float co[2], float uv[2]) { - float m[3], v1[3], v2[3], c1, c2; - int id1, id2; + BMLoop *l; + MLoopUV *luv; + BMIter iter; + float m[3], v1[3], v2[3], c1, c2, *uv1, *uv2, *uv3; + int id1, id2, i; - id1= (id+nverts-1)%nverts; - id2= (id+nverts+1)%nverts; + id1= (id+efa->len-1)%efa->len; + id2= (id+efa->len+1)%efa->len; m[0]= co[0]-uv[0]; m[1]= co[1]-uv[1]; - Vec2Subf(v1, tf->uv[id1], tf->uv[id]); - Vec2Subf(v2, tf->uv[id2], tf->uv[id]); + + i = 0; + BM_ITER(l, &iter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + if (i == id1) + uv1 = luv->uv; + else if (i == id) + uv2 = luv->uv; + else if (i == id2) + uv3 = luv->uv; + + i++; + } + + VecSubf(v1, uv1, uv); + VecSubf(v2, uv3, uv); /* m and v2 on same side of v-v1? */ c1= v1[0]*m[1] - v1[1]*m[0]; @@ -551,83 +704,103 @@ static int nearest_uv_between(MTFace *tf, int nverts, int id, float co[2], float return (c1*c2 >= 0.0f); } -static void find_nearest_uv_vert(Scene *scene, Image *ima, EditMesh *em, float co[2], float penalty[2], NearestHit *hit) +static void find_nearest_uv_vert(Scene *scene, Image *ima, BMEditMesh *em, + float co[2], float penalty[2], NearestHit *hit) { - EditFace *efa; - EditVert *eve; - MTFace *tf; + BMFace *efa; + BMVert *eve; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; float mindist, dist; int i, nverts; + /*this will fill in hit.vert1 and hit.vert2*/ + find_nearest_uv_edge(scene, ima, em, co, hit); + hit->l = hit->nextl = NULL; + hit->luv = hit->nextluv = NULL; + mindist= 1e10f; memset(hit, 0, sizeof(*hit)); - for(i=0, eve=em->verts.first; eve; eve=eve->next, i++) - eve->tmp.l = i; - - for(efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - if(uvedit_face_visible(scene, ima, efa, tf)) { - nverts= efa->v4? 4: 3; + eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) { + BMINDEX_SET(eve, i); + } - for(i=0; i<nverts; i++) { - if(penalty && uvedit_uv_selected(scene, efa, tf, i)) - dist= fabs(co[0]-tf->uv[i][0])+penalty[0] + fabs(co[1]-tf->uv[i][1])+penalty[1]; - else - dist= fabs(co[0]-tf->uv[i][0]) + fabs(co[1]-tf->uv[i][1]); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + i = 0; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - if(dist<=mindist) { - if(dist==mindist) - if(!nearest_uv_between(tf, nverts, i, co, tf->uv[i])) - continue; + if(penalty && uvedit_uv_selected(em, scene, l)) + dist= fabs(co[0]-luv->uv[0])+penalty[0] + fabs(co[1]-luv->uv[1])+penalty[1]; + else + dist= fabs(co[0]-luv->uv[0]) + fabs(co[1]-luv->uv[1]); - mindist= dist; + if(dist<=mindist) { + if(dist==mindist) + if(!nearest_uv_between(em, efa, efa->len, i, co, luv->uv)) { + i++; + continue; + } - hit->uv= i; - hit->tf= tf; - hit->efa= efa; + mindist= dist; - hit->vert= (*(&efa->v1 + i))->tmp.l; - } + hit->l = l; + hit->nextl = (BMLoop*)l->head.next; + hit->luv = luv; + hit->nextluv = CustomData_bmesh_get(&em->bm->ldata, l->head.next->data, CD_MLOOPUV); + hit->tf= tf; + hit->efa= efa; + hit->lindex = i; + hit->vert1 = BMINDEX_GET(hit->l->v); } + + i++; } } } int ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, float co[2], float uv[2]) { - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); - EditFace *efa; - MTFace *tf; + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; float mindist, dist; - int i, nverts, found= 0; + int found= 0; mindist= 1e10f; uv[0]= co[0]; uv[1]= co[1]; - for(efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - if(uvedit_face_visible(scene, ima, efa, tf)) { - nverts= efa->v4? 4: 3; - - for(i=0; i<nverts; i++) { - dist= fabs(co[0]-tf->uv[i][0]) + fabs(co[1]-tf->uv[i][1]); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + dist= fabs(co[0]-luv->uv[0]) + fabs(co[1]-luv->uv[1]); - if(dist<=mindist) { - mindist= dist; + if(dist<=mindist) { + mindist= dist; - uv[0]= tf->uv[i][0]; - uv[1]= tf->uv[i][1]; - found= 1; - } + uv[0]= luv->uv[0]; + uv[1]= luv->uv[1]; + found= 1; } } } - BKE_mesh_end_editmesh(obedit->data, em); return found; } @@ -649,26 +822,28 @@ static void uv_vertex_loop_flag(UvMapVert *first) first->flag= 1; } -static UvMapVert *uv_vertex_map_get(UvVertMap *vmap, EditFace *efa, int a) +static UvMapVert *uv_vertex_map_get(UvVertMap *vmap, BMFace *efa, int a) { UvMapVert *iterv, *first; - - first= EM_get_uv_map_vert(vmap, (*(&efa->v1 + a))->tmp.l); + BMLoop *l; + + l = BMIter_AtIndex(NULL, BM_LOOPS_OF_FACE, efa, a); + first= EDBM_get_uv_map_vert(vmap, BMINDEX_GET(l->v)); for(iterv=first; iterv; iterv=iterv->next) { if(iterv->separate) first= iterv; - if(iterv->f == efa->tmp.l) + if(iterv->f == BMINDEX_GET(efa)) return first; } return NULL; } -static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface) +static int uv_edge_tag_faces(BMEditMesh *em, UvMapVert *first1, UvMapVert *first2, int *totface) { UvMapVert *iterv1, *iterv2; - EditFace *efa; + BMFace *efa; int tot = 0; /* count number of faces this edge has */ @@ -682,8 +857,8 @@ static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface) if(iterv1->f == iterv2->f) { /* if face already tagged, don't do this edge */ - efa= EM_get_face_for_index(iterv1->f); - if(efa->f1) + efa= EDBM_get_face_for_index(em, iterv1->f); + if(BMO_TestFlag(em->bm, efa, EFA_F1_FLAG)) return 0; tot++; @@ -707,8 +882,8 @@ static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface) break; if(iterv1->f == iterv2->f) { - efa= EM_get_face_for_index(iterv1->f); - efa->f1= 1; + efa= EDBM_get_face_for_index(em, iterv1->f); + BMO_SetFlag(em->bm, efa, EFA_F1_FLAG); break; } } @@ -717,41 +892,47 @@ static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface) return 1; } -static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *hit, float limit[2], int extend) +static int select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestHit *hit, float limit[2], int extend) { - EditVert *eve; - EditFace *efa; - MTFace *tf; + BMVert *eve; + BMFace *efa; + BMIter iter, liter; + BMLoop *l; + MTexPoly *tf; UvVertMap *vmap; UvMapVert *iterv1, *iterv2; int a, count, looking, nverts, starttotf, select; /* setup */ - EM_init_index_arrays(em, 0, 0, 1); - vmap= EM_make_uv_vert_map(em, 0, 0, limit); + EDBM_init_index_arrays(em, 0, 0, 1); + vmap= EDBM_make_uv_vert_map(em, 0, 0, limit); - for(count=0, eve=em->verts.first; eve; count++, eve= eve->next) - eve->tmp.l = count; + count = 0; + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + BMINDEX_SET(eve, count); + count++; + } - for(count=0, efa= em->faces.first; efa; count++, efa= efa->next) { + count = 0; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { if(!extend) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - uvedit_face_deselect(scene, efa, tf); + uvedit_face_deselect(scene, em, efa); } - - efa->tmp.l= count; - efa->f1= 0; + + BMO_ClearFlag(em->bm, efa, EFA_F1_FLAG); + BMINDEX_SET(efa, count); + count++; } - + /* set flags for first face and verts */ - nverts= (hit->efa->v4)? 4: 3; - iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge); - iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts); + nverts= hit->efa->len; + iterv1= uv_vertex_map_get(vmap, hit->efa, hit->lindex); + iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->lindex+1)%nverts); uv_vertex_loop_flag(iterv1); uv_vertex_loop_flag(iterv2); starttotf= 0; - uv_edge_tag_faces(iterv1, iterv2, &starttotf); + uv_edge_tag_faces(em, iterv1, iterv2, &starttotf); /* sorry, first edge isnt even ok */ if(iterv1->flag==0 && iterv2->flag==0) looking= 0; @@ -762,21 +943,25 @@ static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *h looking= 0; /* find correct valence edges which are not tagged yet, but connect to tagged one */ - for(efa= em->faces.first; efa; efa=efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(!efa->f1 && uvedit_face_visible(scene, ima, efa, tf)) { - nverts= (efa->v4)? 4: 3; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + + if(!BMO_TestFlag(em->bm, efa, EFA_F1_FLAG) && uvedit_face_visible(scene, ima, efa, tf)) { + nverts= efa->len; for(a=0; a<nverts; a++) { /* check face not hidden and not tagged */ iterv1= uv_vertex_map_get(vmap, efa, a); iterv2= uv_vertex_map_get(vmap, efa, (a+1)%nverts); + + if (!iterv1 || !iterv2) + continue; /* check if vertex is tagged and has right valence */ if(iterv1->flag || iterv2->flag) { - if(uv_edge_tag_faces(iterv1, iterv2, &starttotf)) { + if(uv_edge_tag_faces(em, iterv1, iterv2, &starttotf)) { looking= 1; - efa->f1= 1; + BMO_SetFlag(em->bm, efa, EFA_F1_FLAG); uv_vertex_loop_flag(iterv1); uv_vertex_loop_flag(iterv2); @@ -789,16 +974,14 @@ static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *h } /* do the actual select/deselect */ - nverts= (hit->efa->v4)? 4: 3; - iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge); - iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts); + nverts= hit->efa->len; + iterv1= uv_vertex_map_get(vmap, hit->efa, hit->lindex); + iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->lindex+1)%nverts); iterv1->flag= 1; iterv2->flag= 1; if(extend) { - tf= CustomData_em_get(&em->fdata, hit->efa->data, CD_MTFACE); - - if(uvedit_uv_selected(scene, hit->efa, tf, hit->edge) && uvedit_uv_selected(scene, hit->efa, tf, hit->edge)) + if(uvedit_uv_selected(em, scene, hit->l) && uvedit_uv_selected(em, scene, hit->l)) select= 0; else select= 1; @@ -806,66 +989,82 @@ static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *h else select= 1; - for(efa= em->faces.first; efa; efa=efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf= CustomData_em_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - nverts= (efa->v4)? 4: 3; - for(a=0; a<nverts; a++) { + a = 0; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { iterv1= uv_vertex_map_get(vmap, efa, a); if(iterv1->flag) { - if(select) uvedit_uv_select(scene, efa, tf, a); - else uvedit_uv_deselect(scene, efa, tf, a); + if(select) uvedit_uv_select(em, scene, l); + else uvedit_uv_deselect(em, scene, l); } + + a++; } } /* cleanup */ - EM_free_uv_vert_map(vmap); - EM_free_index_arrays(); + EDBM_free_uv_vert_map(vmap); + EDBM_free_index_arrays(em); return (select)? 1: -1; } /*********************** linked select ***********************/ -static void select_linked(Scene *scene, Image *ima, EditMesh *em, float limit[2], NearestHit *hit, int extend) +static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, float limit[2], NearestHit *hit, int extend) { - EditFace *efa; - MTFace *tf; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; UvVertMap *vmap; UvMapVert *vlist, *iterv, *startv; int a, i, nverts, j, stacksize= 0, *stack; char *flag; - vmap= EM_make_uv_vert_map(em, 1, 1, limit); + vmap= EDBM_make_uv_vert_map(em, 1, 1, limit); if(vmap == NULL) return; - stack= MEM_mallocN(sizeof(*stack)* BLI_countlist(&em->faces), "UvLinkStack"); - flag= MEM_callocN(sizeof(*flag)*BLI_countlist(&em->faces), "UvLinkFlag"); + stack= MEM_mallocN(sizeof(*stack)*em->bm->totface, "UvLinkStack"); + flag= MEM_callocN(sizeof(*flag)*em->bm->totface, "UvLinkFlag"); if(!hit) { - for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + a = 0; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - if(uvedit_face_visible(scene, ima, efa, tf)) { - if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) { - stack[stacksize]= a; - stacksize++; - flag[a]= 1; + if(uvedit_face_visible(scene, ima, efa, tf)) { + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + if (luv->flag & MLOOPUV_VERTSEL) { + stack[stacksize]= a; + stacksize++; + flag[a]= 1; + + break; + } } } } + a++; } else { - for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) { + a = 0; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { if(efa == hit->efa) { stack[stacksize]= a; stacksize++; flag[a]= 1; break; } + + a++; } } @@ -873,15 +1072,21 @@ static void select_linked(Scene *scene, Image *ima, EditMesh *em, float limit[2] stacksize--; a= stack[stacksize]; - for(j=0, efa= em->faces.first; efa; efa= efa->next, j++) + j = 0; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { if(j==a) break; - nverts= efa->v4? 4: 3; + j++; + } + + nverts= efa->len; + + i = 0; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { - for(i=0; i<nverts; i++) { /* make_uv_vert_map_EM sets verts tmp.l to the indicies */ - vlist= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l); + vlist= EDBM_get_uv_map_vert(vmap, BMINDEX_GET(l->v)); startv= vlist; @@ -897,56 +1102,74 @@ static void select_linked(Scene *scene, Image *ima, EditMesh *em, float limit[2] break; else if(!flag[iterv->f]) { flag[iterv->f]= 1; - stack[stacksize]= iterv->f;; + stack[stacksize]= iterv->f; stacksize++; } } + + i++; } } - if(!extend || hit) { - for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(flag[a]) - tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); - else - tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); + if(!extend || hit) { + a = 0; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + if (flag[a]) + luv->flag |= MLOOPUV_VERTSEL; + else + luv->flag &= ~MLOOPUV_VERTSEL; + } } } else if(extend && hit) { - for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) { - if(flag[a]) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(efa->v4) { - if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4))) - break; - } - else if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) + a = 0; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + if (luv->flag & MLOOPUV_VERTSEL) break; } + + a++; } if(efa) { - for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) { - if(flag[a]) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); + a = 0; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!flag[a]) continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + luv->flag &= ~MLOOPUV_VERTSEL; } + + a++; } } else { - for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) { - if(flag[a]) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); + a = 0; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!flag[a]) continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + luv->flag |= MLOOPUV_VERTSEL; } + + a++; } } } MEM_freeN(stack); MEM_freeN(flag); - EM_free_uv_vert_map(vmap); + EDBM_free_uv_vert_map(vmap); } /* ******************** align operator **************** */ @@ -956,31 +1179,33 @@ static void weld_align_uv(bContext *C, int tool) Scene *scene; Object *obedit; Image *ima; - EditMesh *em; - EditFace *efa; - MTFace *tf; + BMEditMesh *em; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; float cent[2], min[2], max[2]; scene= CTX_data_scene(C); obedit= CTX_data_edit_object(C); - em= BKE_mesh_get_editmesh((Mesh*)obedit->data); + em= ((Mesh*)obedit->data)->edit_btmesh; ima= CTX_data_edit_image(C); INIT_MINMAX2(min, max); if(tool == 'a') { - for(efa= em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - if(uvedit_face_visible(scene, ima, efa, tf)) { - if(uvedit_uv_selected(scene, efa, tf, 0)) - DO_MINMAX2(tf->uv[0], min, max) - if(uvedit_uv_selected(scene, efa, tf, 1)) - DO_MINMAX2(tf->uv[1], min, max) - if(uvedit_uv_selected(scene, efa, tf, 2)) - DO_MINMAX2(tf->uv[2], min, max) - if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) - DO_MINMAX2(tf->uv[3], min, max) + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if (uvedit_uv_selected(em, scene, l)) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + DO_MINMAX2(luv->uv, min, max) + } } } @@ -990,41 +1215,39 @@ static void weld_align_uv(bContext *C, int tool) uvedit_center(scene, ima, obedit, cent, 0); if(tool == 'x' || tool == 'w') { - for(efa= em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(uvedit_face_visible(scene, ima, efa, tf)) { - if(uvedit_uv_selected(scene, efa, tf, 0)) - tf->uv[0][0]= cent[0]; - if(uvedit_uv_selected(scene, efa, tf, 1)) - tf->uv[1][0]= cent[0]; - if(uvedit_uv_selected(scene, efa, tf, 2)) - tf->uv[2][0]= cent[0]; - if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) - tf->uv[3][0]= cent[0]; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if (uvedit_uv_selected(em, scene, l)) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv->uv[0] = cent[0]; + } + } } } if(tool == 'y' || tool == 'w') { - for(efa= em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(uvedit_face_visible(scene, ima, efa, tf)) { - if(uvedit_uv_selected(scene, efa, tf, 0)) - tf->uv[0][1]= cent[1]; - if(uvedit_uv_selected(scene, efa, tf, 1)) - tf->uv[1][1]= cent[1]; - if(uvedit_uv_selected(scene, efa, tf, 2)) - tf->uv[2][1]= cent[1]; - if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) - tf->uv[3][1]= cent[1]; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if (uvedit_uv_selected(em, scene, l)) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv->uv[1] = cent[1]; + } + } } } DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); } static int align_exec(bContext *C, wmOperator *op) @@ -1089,36 +1312,39 @@ static int stitch_exec(bContext *C, wmOperator *op) SpaceImage *sima; Scene *scene; Object *obedit; - EditMesh *em; - EditFace *efa; - EditVert *eve; + BMEditMesh *em; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + BMVert *eve; Image *ima; - MTFace *tf; + MTexPoly *tf; + MLoopUV *luv; sima= CTX_wm_space_image(C); scene= CTX_data_scene(C); obedit= CTX_data_edit_object(C); - em= BKE_mesh_get_editmesh((Mesh*)obedit->data); + em= ((Mesh*)obedit->data)->edit_btmesh; ima= CTX_data_edit_image(C); if(RNA_boolean_get(op->ptr, "use_limit")) { UvVertMap *vmap; UvMapVert *vlist, *iterv; - float newuv[2], limit[2]; + float newuv[2], limit[2], pixels; int a, vtot; - limit[0]= RNA_float_get(op->ptr, "limit"); - limit[1]= limit[0]; + pixels= RNA_float_get(op->ptr, "limit"); + uvedit_pixel_to_float(sima, limit, pixels); - EM_init_index_arrays(em, 0, 0, 1); - vmap= EM_make_uv_vert_map(em, 1, 0, limit); + EDBM_init_index_arrays(em, 0, 0, 1); + vmap= EDBM_make_uv_vert_map(em, 1, 0, limit); if(vmap == NULL) { - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED; } - - for(a=0, eve= em->verts.first; eve; a++, eve= eve->next) { + + a = 0; + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { vlist= EM_get_uv_map_vert(vmap, a); while(vlist) { @@ -1129,12 +1355,15 @@ static int stitch_exec(bContext *C, wmOperator *op) if((iterv != vlist) && iterv->separate) break; - efa = EM_get_face_for_index(iterv->f); - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + efa = EDBM_get_face_for_index(em, iterv->f); + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - if(uvedit_uv_selected(scene, efa, tf, iterv->tfindex)) { - newuv[0] += tf->uv[iterv->tfindex][0]; - newuv[1] += tf->uv[iterv->tfindex][1]; + l = BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex); + if (uvedit_uv_selected(em, scene, l)) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + newuv[0] += luv->uv[0]; + newuv[1] += luv->uv[1]; vtot++; } } @@ -1146,95 +1375,72 @@ static int stitch_exec(bContext *C, wmOperator *op) if((iterv != vlist) && iterv->separate) break; - efa = EM_get_face_for_index(iterv->f); - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + efa = EDBM_get_face_for_index(em, iterv->f); + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + + l = BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex); + if (uvedit_uv_selected(em, scene, l)) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - if(uvedit_uv_selected(scene, efa, tf, iterv->tfindex)) { - tf->uv[iterv->tfindex][0]= newuv[0]; - tf->uv[iterv->tfindex][1]= newuv[1]; + luv->uv[0] = newuv[0]; + luv->uv[1] = newuv[1]; + vtot++; } } } vlist= iterv; } + + a++; } - EM_free_uv_vert_map(vmap); - EM_free_index_arrays(); + EDBM_free_uv_vert_map(vmap); + EDBM_free_index_arrays(em); } else { UVVertAverage *uv_average, *uvav; int count; // index and count verts - for(count=0, eve=em->verts.first; eve; count++, eve= eve->next) - eve->tmp.l = count; + count=0; + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + BMINDEX_SET(eve, count); + count++; + } uv_average= MEM_callocN(sizeof(UVVertAverage)*count, "Stitch"); // gather uv averages per vert - for(efa= em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - if(uvedit_face_visible(scene, ima, efa, tf)) { - if(uvedit_uv_selected(scene, efa, tf, 0)) { - uvav = uv_average + efa->v1->tmp.l; - uvav->count++; - uvav->uv[0] += tf->uv[0][0]; - uvav->uv[1] += tf->uv[0][1]; - } - - if(uvedit_uv_selected(scene, efa, tf, 1)) { - uvav = uv_average + efa->v2->tmp.l; - uvav->count++; - uvav->uv[0] += tf->uv[1][0]; - uvav->uv[1] += tf->uv[1][1]; - } - - if(uvedit_uv_selected(scene, efa, tf, 2)) { - uvav = uv_average + efa->v3->tmp.l; - uvav->count++; - uvav->uv[0] += tf->uv[2][0]; - uvav->uv[1] += tf->uv[2][1]; - } + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if(uvedit_uv_selected(em, scene, l)) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + uvav = uv_average + BMINDEX_GET(l->v); - if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) { - uvav = uv_average + efa->v4->tmp.l; uvav->count++; - uvav->uv[0] += tf->uv[3][0]; - uvav->uv[1] += tf->uv[3][1]; + uvav->uv[0] += luv->uv[0]; + uvav->uv[1] += luv->uv[1]; } } } // apply uv welding - for(efa= em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - if(uvedit_face_visible(scene, ima, efa, tf)) { - if(uvedit_uv_selected(scene, efa, tf, 0)) { - uvav = uv_average + efa->v1->tmp.l; - tf->uv[0][0] = uvav->uv[0]/uvav->count; - tf->uv[0][1] = uvav->uv[1]/uvav->count; - } - - if(uvedit_uv_selected(scene, efa, tf, 1)) { - uvav = uv_average + efa->v2->tmp.l; - tf->uv[1][0] = uvav->uv[0]/uvav->count; - tf->uv[1][1] = uvav->uv[1]/uvav->count; - } - - if(uvedit_uv_selected(scene, efa, tf, 2)) { - uvav = uv_average + efa->v3->tmp.l; - tf->uv[2][0] = uvav->uv[0]/uvav->count; - tf->uv[2][1] = uvav->uv[1]/uvav->count; - } - - if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) { - uvav = uv_average + efa->v4->tmp.l; - tf->uv[3][0] = uvav->uv[0]/uvav->count; - tf->uv[3][1] = uvav->uv[1]/uvav->count; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if(uvedit_uv_selected(em, scene, l)) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + uvav = uv_average + BMINDEX_GET(l->v); + luv->uv[0] = uvav->uv[0]/uvav->count; + luv->uv[1] = uvav->uv[1]/uvav->count; } } } @@ -1245,7 +1451,6 @@ static int stitch_exec(bContext *C, wmOperator *op) DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -1262,7 +1467,7 @@ void UV_OT_stitch(wmOperatorType *ot) /* properties */ RNA_def_boolean(ot->srna, "use_limit", 1, "Use Limit", "Stitch UVs within a specified limit distance."); - RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, FLT_MAX, "Limit", "Limit distance in normalized coordinates.", -FLT_MAX, FLT_MAX); + RNA_def_float(ot->srna, "limit", 20.0, 0.0f, FLT_MAX, "Limit", "Limit distance in image pixels.", -FLT_MAX, FLT_MAX); } /* ******************** (de)select all operator **************** */ @@ -1272,36 +1477,39 @@ static int select_inverse_exec(bContext *C, wmOperator *op) Scene *scene; ToolSettings *ts; Object *obedit; - EditMesh *em; - EditFace *efa; + BMEditMesh *em; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; Image *ima; - MTFace *tf; + MTexPoly *tf; + MLoopUV *luv; scene= CTX_data_scene(C); ts= CTX_data_tool_settings(C); obedit= CTX_data_edit_object(C); - em= BKE_mesh_get_editmesh((Mesh*)obedit->data); + em= ((Mesh*)obedit->data)->edit_btmesh; ima= CTX_data_edit_image(C); if(ts->uv_flag & UV_SYNC_SELECTION) { - EM_select_swap(em); + EDBM_select_swap(em); } else { - for(efa= em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_em_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - if(uvedit_face_visible(scene, ima, efa, tf)) { - tf->flag ^= TF_SEL1; - tf->flag ^= TF_SEL2; - tf->flag ^= TF_SEL3; - if(efa->v4) tf->flag ^= TF_SEL4; + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv->flag = luv->flag ^ MLOOPUV_VERTSEL; } } } WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -1324,54 +1532,59 @@ static int de_select_all_exec(bContext *C, wmOperator *op) Scene *scene; ToolSettings *ts; Object *obedit; - EditMesh *em; - EditFace *efa; + BMEditMesh *em; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; Image *ima; - MTFace *tf; - int sel; + MTexPoly *tf; + MLoopUV *luv; + int sel = 1; scene= CTX_data_scene(C); ts= CTX_data_tool_settings(C); obedit= CTX_data_edit_object(C); - em= BKE_mesh_get_editmesh((Mesh*)obedit->data); + em= ((Mesh*)obedit->data)->edit_btmesh; ima= CTX_data_edit_image(C); if(ts->uv_flag & UV_SYNC_SELECTION) { - EM_toggle_select_all(em); + EDBM_toggle_select_all(((Mesh*)obedit->data)->edit_btmesh); } else { - sel= 0; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - for(efa= em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; - if(uvedit_face_visible(scene, ima, efa, tf)) { - if(tf->flag & (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4)) { - sel= 1; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + if (luv->flag & MLOOPUV_VERTSEL) { + sel= 0; break; } } } - for(efa= em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - if(uvedit_face_visible(scene, ima, efa, tf)) { - if(efa->v4) { - if(sel) tf->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4); - else tf->flag |= (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4); - } - else { - if(sel) tf->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4); - else tf->flag |= (TF_SEL1+TF_SEL2+TF_SEL3); - } + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + if (sel) luv->flag |= MLOOPUV_VERTSEL; + else luv->flag &= ~MLOOPUV_VERTSEL; } } } WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -1389,7 +1602,7 @@ void UV_OT_select_all_toggle(wmOperatorType *ot) /* ******************** mouse select operator **************** */ -static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], float *uv, int sticky) +static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], float *uv, int sticky, int hitlen) { int i; @@ -1398,7 +1611,7 @@ static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], floa if(sticky == SI_STICKY_DISABLE) return 0; - for(i=0; i<4; i++) { + for(i=0; i<hitlen; i++) { if(hitv[i] == v) { if(sticky == SI_STICKY_LOC) { if(fabs(hituv[i][0]-uv[0]) < limit[0] && fabs(hituv[i][1]-uv[1]) < limit[1]) @@ -1419,14 +1632,20 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop) ToolSettings *ts= CTX_data_tool_settings(C); Object *obedit= CTX_data_edit_object(C); Image *ima= CTX_data_edit_image(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); - EditFace *efa; - MTFace *tf; + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; NearestHit hit; - int a, i, select = 1, selectmode, sticky, sync, hitv[4], nvert; - int flush = 0; /* 0 == dont flush, 1 == sel, -1 == desel; only use when selection sync is enabled */ - float limit[2], *hituv[4], penalty[2]; - + int a, i, select = 1, selectmode, sticky, sync, *hitv=NULL, nvert; + BLI_array_declare(hitv); + int flush = 0, hitlen=0; /* 0 == dont flush, 1 == sel, -1 == desel; only use when selection sync is enabled */ + float limit[2], **hituv = NULL; + BLI_array_declare(hituv); + float penalty[2]; + uvedit_pixel_to_float(sima, limit, 0.05f); uvedit_pixel_to_float(sima, penalty, 5.0f); @@ -1446,7 +1665,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop) else { sync= 0; selectmode= ts->uv_selectmode; - sticky= (sima)? sima->sticky: 1; + sticky= sima->sticky; } /* find nearest element */ @@ -1454,76 +1673,88 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop) /* find edge */ find_nearest_uv_edge(scene, ima, em, co, &hit); if(hit.efa == NULL) { - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED; } + + hitlen = 0; } else if(selectmode == UV_SELECT_VERTEX) { /* find vertex */ find_nearest_uv_vert(scene, ima, em, co, penalty, &hit); if(hit.efa == NULL) { - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED; } /* mark 1 vertex as being hit */ - for(i=0; i<4; i++) + for(i=0; i<hit.efa->len; i++) { + BLI_array_growone(hitv); + BLI_array_growone(hituv); hitv[i]= 0xFFFFFFFF; + } + + hitv[hit.lindex]= hit.vert1; + hituv[hit.lindex]= hit.luv->uv; - hitv[hit.uv]= hit.vert; - hituv[hit.uv]= hit.tf->uv[hit.uv]; + hitlen = hit.efa->len; } else if(selectmode == UV_SELECT_EDGE) { /* find edge */ find_nearest_uv_edge(scene, ima, em, co, &hit); if(hit.efa == NULL) { - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED; } /* mark 2 edge vertices as being hit */ - for(i=0; i<4; i++) + for(i=0; i<hit.efa->len; i++) { + BLI_array_growone(hitv); + BLI_array_growone(hituv); hitv[i]= 0xFFFFFFFF; + } + + nvert= hit.efa->len; - nvert= (hit.efa->v4)? 4: 3; + hitv[hit.lindex]= hit.vert1; + hitv[(hit.lindex+1)%nvert]= hit.vert2; + hituv[hit.lindex]= hit.luv->uv; + hituv[(hit.lindex+1)%nvert]= hit.nextluv->uv; - hitv[hit.edge]= hit.vert; - hitv[(hit.edge+1)%nvert]= hit.vert2; - hituv[hit.edge]= hit.tf->uv[hit.edge]; - hituv[(hit.edge+1)%nvert]= hit.tf->uv[(hit.edge+1)%nvert]; + hitlen = hit.efa->len; } else if(selectmode == UV_SELECT_FACE) { /* find face */ find_nearest_uv_face(scene, ima, em, co, &hit); if(hit.efa == NULL) { - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED; } /* make active */ - EM_set_actFace(em, hit.efa); + EDBM_set_actFace(em, hit.efa); /* mark all face vertices as being hit */ - for(i=0; i<4; i++) - hituv[i]= hit.tf->uv[i]; + i = 0; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, hit.efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - hitv[0]= hit.efa->v1->tmp.l; - hitv[1]= hit.efa->v2->tmp.l; - hitv[2]= hit.efa->v3->tmp.l; + BLI_array_growone(hitv); + BLI_array_growone(hituv); + hituv[i]= luv->uv; + hitv[i] = BMINDEX_GET(l->v); + i++; + } - if(hit.efa->v4) hitv[3]= hit.efa->v4->tmp.l; - else hitv[3]= 0xFFFFFFFF; + hitlen = hit.efa->len; } else if(selectmode == UV_SELECT_ISLAND) { find_nearest_uv_vert(scene, ima, em, co, NULL, &hit); if(hit.efa==NULL) { - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED; } + + hitlen = 0; } else { - BKE_mesh_end_editmesh(obedit->data, em); + hitlen = 0; return OPERATOR_CANCELLED; } @@ -1537,36 +1768,36 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop) else if(extend) { if(selectmode == UV_SELECT_VERTEX) { /* (de)select uv vertex */ - if(uvedit_uv_selected(scene, hit.efa, hit.tf, hit.uv)) { - uvedit_uv_deselect(scene, hit.efa, hit.tf, hit.uv); + if(uvedit_uv_selected(em, scene, hit.l)) { + uvedit_uv_deselect(em, scene, hit.l); select= 0; } else { - uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv); + uvedit_uv_select(em, scene, hit.l); select= 1; } flush = 1; } else if(selectmode == UV_SELECT_EDGE) { /* (de)select edge */ - if(uvedit_edge_selected(scene, hit.efa, hit.tf, hit.edge)) { - uvedit_edge_deselect(scene, hit.efa, hit.tf, hit.edge); + if(uvedit_edge_selected(em, scene, hit.l)) { + uvedit_edge_deselect(em, scene, hit.l); select= 0; } else { - uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge); + uvedit_edge_select(em, scene, hit.l); select= 1; } flush = 1; } else if(selectmode == UV_SELECT_FACE) { /* (de)select face */ - if(uvedit_face_selected(scene, hit.efa, hit.tf)) { - uvedit_face_deselect(scene, hit.efa, hit.tf); + if(uvedit_face_selected(scene, em, hit.efa)) { + uvedit_face_deselect(scene, em, hit.efa); select= 0; } else { - uvedit_face_select(scene, hit.efa, hit.tf); + uvedit_face_select(scene, em, hit.efa); select= 1; } flush = -1; @@ -1574,97 +1805,89 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop) /* (de)select sticky uv nodes */ if(sticky != SI_STICKY_DISABLE) { - EditVert *ev; - - for(a=0, ev=em->verts.first; ev; ev = ev->next, a++) - ev->tmp.l = a; + BMVert *ev; + a = 0; + BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + BMINDEX_SET(ev, a); + a++; + } + /* deselect */ if(select==0) { - for(efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - if(uvedit_face_visible(scene, ima, efa, tf)) { - if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky)) - uvedit_uv_deselect(scene, efa, tf, 0); - if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky)) - uvedit_uv_deselect(scene, efa, tf, 1); - if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky)) - uvedit_uv_deselect(scene, efa, tf, 2); - if(efa->v4) - if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky)) - uvedit_uv_deselect(scene, efa, tf, 3); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf= CustomData_em_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + if(sticky_select(limit, hitv, BMINDEX_GET(l->v), hituv, luv->uv, sticky, hitlen)) + uvedit_uv_deselect(em, scene, l); } } flush = -1; } /* select */ else { - for(efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - if(uvedit_face_visible(scene, ima, efa, tf)) { - if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky)) - uvedit_uv_select(scene, efa, tf, 0); - if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky)) - uvedit_uv_select(scene, efa, tf, 1); - if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky)) - uvedit_uv_select(scene, efa, tf, 2); - if(efa->v4) - if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky)) - uvedit_uv_select(scene, efa, tf, 3); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + if(sticky_select(limit, hitv, BMINDEX_GET(l->v), hituv, luv->uv, sticky, hitlen)) + uvedit_uv_select(em, scene, l); } } - + flush = 1; } } } else { /* deselect all */ - for(efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - uvedit_face_deselect(scene, efa, tf); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + uvedit_face_deselect(scene, em, efa); } if(selectmode == UV_SELECT_VERTEX) { /* select vertex */ - uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv); + uvedit_uv_select(em, scene, hit.l); flush= 1; } else if(selectmode == UV_SELECT_EDGE) { /* select edge */ - uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge); + uvedit_edge_select(em, scene, hit.l); flush= 1; } else if(selectmode == UV_SELECT_FACE) { /* select face */ - uvedit_face_select(scene, hit.efa, hit.tf); + uvedit_face_select(scene, em, hit.efa); } /* select sticky uvs */ if(sticky != SI_STICKY_DISABLE) { - for(efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(uvedit_face_visible(scene, ima, efa, tf)) { + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf= CustomData_em_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { if(sticky == SI_STICKY_DISABLE) continue; + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky)) - uvedit_uv_select(scene, efa, tf, 0); - if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky)) - uvedit_uv_select(scene, efa, tf, 1); - if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky)) - uvedit_uv_select(scene, efa, tf, 2); - if(efa->v4) - if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky)) - uvedit_uv_select(scene, efa, tf, 3); + if(sticky_select(limit, hitv, BMINDEX_GET(l->v), hituv, luv->uv, sticky, hitlen)) + uvedit_uv_select(em, scene, l); flush= 1; } } } } - +#if 0 //bmesh does flushing through the BM_Select functions, so not sure + //what to do about this bit. if(sync) { /* flush for mesh selection */ if(ts->selectmode != SCE_SELECT_FACE) { @@ -1672,11 +1895,10 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop) else if(flush==-1) EM_deselect_flush(em); } } - +#endif DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_PASS_THROUGH|OPERATOR_FINISHED; } @@ -1783,13 +2005,12 @@ static int select_linked_exec(bContext *C, wmOperator *op) ToolSettings *ts= CTX_data_tool_settings(C); Object *obedit= CTX_data_edit_object(C); Image *ima= CTX_data_edit_image(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; float limit[2]; int extend; if(ts->uv_flag & UV_SYNC_SELECTION) { BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled."); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED; } @@ -1800,7 +2021,6 @@ static int select_linked_exec(bContext *C, wmOperator *op) DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -1828,27 +2048,38 @@ static int unlink_selection_exec(bContext *C, wmOperator *op) ToolSettings *ts= CTX_data_tool_settings(C); Object *obedit= CTX_data_edit_object(C); Image *ima= CTX_data_edit_image(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); - EditFace *efa; - MTFace *tf; + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; if(ts->uv_flag & UV_SYNC_SELECTION) { BKE_report(op->reports, RPT_ERROR, "Can't unlink selection when sync selection is enabled."); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED; } - for(efa= em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + int desel = 0; - if(uvedit_face_visible(scene, ima, efa, tf)) { - if(efa->v4) { - if(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) - tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->pdata, l->head.data, CD_MLOOPUV); + + if (!(luv->flag & MLOOPUV_VERTSEL)) { + desel = 1; + break; } - else { - if(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) - tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3); + } + + if (desel) { + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->pdata, l->head.data, CD_MLOOPUV); + luv->flag &= ~MLOOPUV_VERTSEL; } } } @@ -1856,7 +2087,6 @@ static int unlink_selection_exec(bContext *C, wmOperator *op) DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -1890,78 +2120,77 @@ static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Obje * selection (so for sticky modes, vertex or location based). */ ToolSettings *ts= CTX_data_tool_settings(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); - EditFace *efa; - MTFace *tf; - int nverts, i; + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_VERTEX) { /* Tag all verts as untouched, then touch the ones that have a face center - * in the loop and select all MTFace UV's that use a touched vert. */ - EditVert *eve; + * in the loop and select all MLoopUV's that use a touched vert. */ + BMVert *eve; - for(eve= em->verts.first; eve; eve= eve->next) - eve->tmp.l = 0; + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) + BMINDEX_SET(eve, 0); - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->tmp.l) { - if(efa->v4) - efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= efa->v4->tmp.l=1; - else - efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= 1; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if(BMINDEX_GET(efa)) { + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + BMINDEX_SET(l->v, 1); + } } } /* now select tagged verts */ - for(efa= em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - nverts= efa->v4? 4: 3; - for(i=0; i<nverts; i++) { - if((*(&efa->v1 + i))->tmp.l) { - if(select) - uvedit_uv_select(scene, efa, tf, i); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if (BMINDEX_GET(l->v)) { + if (select) + uvedit_uv_select(em, scene, l); else - uvedit_uv_deselect(scene, efa, tf, i); + uvedit_uv_deselect(em, scene, l); } } } } else if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_LOC) { - EditFace *efa_vlist; - MTFace *tf_vlist; + BMFace *efa_vlist; + MTexPoly *tf_vlist; UvMapVert *start_vlist=NULL, *vlist_iter; struct UvVertMap *vmap; float limit[2]; int efa_index; - //EditVert *eve; /* removed vert counting for now */ + //BMVert *eve; /* removed vert counting for now */ //int a; uvedit_pixel_to_float(sima, limit, 0.05); - EM_init_index_arrays(em, 0, 0, 1); - vmap= EM_make_uv_vert_map(em, 0, 0, limit); + EDBM_init_index_arrays(em, 0, 0, 1); + vmap= EDBM_make_uv_vert_map(em, 0, 0, limit); /* verts are numbered above in make_uv_vert_map_EM, make sure this stays true! */ /*for(a=0, eve= em->verts.first; eve; a++, eve= eve->next) eve->tmp.l = a; */ if(vmap == NULL) { - BKE_mesh_end_editmesh(obedit->data, em); return; } - for(efa_index=0, efa= em->faces.first; efa; efa_index++, efa= efa->next) { - if(efa->tmp.l) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - nverts= efa->v4? 4: 3; - - for(i=0; i<nverts; i++) { + efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL); + for (efa_index=0; efa; efa=BMIter_Step(&iter), efa_index++) { + if(BMINDEX_GET(efa)) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { if(select) - uvedit_uv_select(scene, efa, tf, i); + uvedit_uv_select(em, scene, l); else - uvedit_uv_deselect(scene, efa, tf, i); + uvedit_uv_deselect(em, scene, l); - vlist_iter= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l); + vlist_iter= EDBM_get_uv_map_vert(vmap, BMINDEX_GET(l->v)); while (vlist_iter) { if(vlist_iter->separate) @@ -1980,35 +2209,33 @@ static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Obje break; if(efa_index != vlist_iter->f) { - efa_vlist = EM_get_face_for_index(vlist_iter->f); - tf_vlist = CustomData_em_get(&em->fdata, efa_vlist->data, CD_MTFACE); + efa_vlist = EDBM_get_face_for_index(em, vlist_iter->f); + tf_vlist = CustomData_bmesh_get(&em->bm->pdata, efa_vlist->head.data, CD_MTEXPOLY); if(select) - uvedit_uv_select(scene, efa_vlist, tf_vlist, vlist_iter->tfindex); + uvedit_uv_select(em, scene, BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->tfindex)); else - uvedit_uv_deselect(scene, efa_vlist, tf_vlist, vlist_iter->tfindex); + uvedit_uv_deselect(em, scene, BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->tfindex)); } vlist_iter = vlist_iter->next; } } } } - EM_free_index_arrays(); - EM_free_uv_vert_map(vmap); + EDBM_free_index_arrays(em); + EDBM_free_uv_vert_map(vmap); } else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */ - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->tmp.l) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if(BMINDEX_GET(efa)) { if(select) - uvedit_face_select(scene, efa, tf); + uvedit_face_select(scene, em, efa); else - uvedit_face_deselect(scene, efa, tf); + uvedit_face_deselect(scene, em, efa); } } } - BKE_mesh_end_editmesh(obedit->data, em); } static int border_select_exec(bContext *C, wmOperator *op) @@ -2019,9 +2246,12 @@ static int border_select_exec(bContext *C, wmOperator *op) Object *obedit= CTX_data_edit_object(C); Image *ima= CTX_data_edit_image(C); ARegion *ar= CTX_wm_region(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); - EditFace *efa; - MTFace *tface; + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; rcti rect; rctf rectf; int change, pinned, select, faces; @@ -2051,14 +2281,16 @@ static int border_select_exec(bContext *C, wmOperator *op) change= 0; - for(efa= em->faces.first; efa; efa= efa->next) { + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { /* assume not touched */ - efa->tmp.l = 0; - tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(uvedit_face_visible(scene, ima, efa, tface)) { - uv_center(tface->uv, cent, efa->v4 != NULL); + BMINDEX_SET(efa, 0); + + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(uvedit_face_visible(scene, ima, efa, tf)) { + poly_uv_center(em, efa, cent); if(BLI_in_rctf(&rectf, cent[0], cent[1])) { - efa->tmp.l = change = 1; + BMINDEX_SET(efa, 1); + change = 1; } } } @@ -2070,51 +2302,26 @@ static int border_select_exec(bContext *C, wmOperator *op) else { /* other selection modes */ change= 1; + + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tf)) + continue; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - for(efa= em->faces.first; efa; efa= efa->next) { - tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(uvedit_face_visible(scene, ima, efa, tface)) { if(!pinned || (ts->uv_flag & UV_SYNC_SELECTION) ) { + /* UV_SYNC_SELECTION - can't do pinned selection */ - if(BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) { - if(select) uvedit_uv_select(scene, efa, tface, 0); - else uvedit_uv_deselect(scene, efa, tface, 0); - } - if(BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) { - if(select) uvedit_uv_select(scene, efa, tface, 1); - else uvedit_uv_deselect(scene, efa, tface, 1); - } - if(BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) { - if(select) uvedit_uv_select(scene, efa, tface, 2); - else uvedit_uv_deselect(scene, efa, tface, 2); - } - if(efa->v4 && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) { - if(select) uvedit_uv_select(scene, efa, tface, 3); - else uvedit_uv_deselect(scene, efa, tface, 3); - } - } - else if(pinned) { - if((tface->unwrap & TF_PIN1) && - BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) { - - if(select) uvedit_uv_select(scene, efa, tface, 0); - else uvedit_uv_deselect(scene, efa, tface, 0); - } - if((tface->unwrap & TF_PIN2) && - BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) { - - if(select) uvedit_uv_select(scene, efa, tface, 1); - else uvedit_uv_deselect(scene, efa, tface, 1); - } - if((tface->unwrap & TF_PIN3) && - BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) { - - if(select) uvedit_uv_select(scene, efa, tface, 2); - else uvedit_uv_deselect(scene, efa, tface, 2); + if(BLI_in_rctf(&rectf, luv->uv[0], luv->uv[1])) { + if(select) uvedit_uv_select(em, scene, l); + else uvedit_uv_deselect(em, scene, l); } - if((efa->v4) && (tface->unwrap & TF_PIN4) && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) { - if(select) uvedit_uv_select(scene, efa, tface, 3); - else uvedit_uv_deselect(scene, efa, tface, 3); + } else if(pinned) { + if ((luv->flag & MLOOPUV_PINNED) && + BLI_in_rctf(&rectf, luv->uv[0], luv->uv[1])) { + if(select) uvedit_uv_select(em, scene, l); + else uvedit_uv_deselect(em, scene, l); } } } @@ -2123,20 +2330,20 @@ static int border_select_exec(bContext *C, wmOperator *op) if(change) { /* make sure newly selected vert selection is updated*/ +#if 0 //ok, I think the BM_Select API handles all of this? if(ts->uv_flag & UV_SYNC_SELECTION) { if(ts->selectmode != SCE_SELECT_FACE) { if(select) EM_select_flush(em); else EM_deselect_flush(em); } } +#endif WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } - - BKE_mesh_end_editmesh(obedit->data, em); + return OPERATOR_CANCELLED; } @@ -2167,20 +2374,23 @@ void UV_OT_select_border(wmOperatorType *ot) /* ******************** circle select operator **************** */ -static void select_uv_inside_ellipse(SpaceImage *sima, Scene *scene, int select, EditFace *efa, MTFace *tface, int index, float *offset, float *ell, int select_index) +static void select_uv_inside_ellipse(BMEditMesh *em, SpaceImage *sima, + Scene *scene, int select, float *offset, + float *ell, BMLoop *l, MLoopUV *luv) { /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ float x, y, r2, *uv; - uv= tface->uv[index]; + + uv= luv->uv; x= (uv[0] - offset[0])*ell[0]; y= (uv[1] - offset[1])*ell[1]; r2 = x*x + y*y; if(r2 < 1.0) { - if(select) uvedit_uv_select(scene, efa, tface, select_index); - else uvedit_uv_deselect(scene, efa, tface, select_index); + if(select) uvedit_uv_select(em, scene, l); + else uvedit_uv_deselect(em, scene, l); } } @@ -2189,10 +2399,13 @@ int circle_select_exec(bContext *C, wmOperator *op) SpaceImage *sima= CTX_wm_space_image(C); Scene *scene= CTX_data_scene(C); Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; ARegion *ar= CTX_wm_region(C); - EditFace *efa; - MTFace *tface; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + MTexPoly *tface; int x, y, radius, width, height, select; float zoomx, zoomy, offset[2], ellipse[2]; @@ -2213,21 +2426,19 @@ int circle_select_exec(bContext *C, wmOperator *op) UI_view2d_region_to_view(&ar->v2d, x, y, &offset[0], &offset[1]); /* do selection */ - for(efa= em->faces.first; efa; efa= efa->next) { - tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - select_uv_inside_ellipse(sima, scene, select, efa, tface, 0, offset, ellipse, 0); - select_uv_inside_ellipse(sima, scene, select, efa, tface, 1, offset, ellipse, 1); - select_uv_inside_ellipse(sima, scene, select, efa, tface, 2, offset, ellipse, 2); - if(efa->v4) - select_uv_inside_ellipse(sima, scene, select, efa, tface, 3, offset, ellipse, 3); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + select_uv_inside_ellipse(em, sima, scene, select, offset, ellipse, l, luv); + } } +#if 0 //I think the BM_Select api stuff handles all this as necassary? if(select) EM_select_flush(em); else EM_deselect_flush(em); - +#endif WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -2325,97 +2536,88 @@ void UV_OT_snap_cursor(wmOperatorType *ot) static int snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, View2D *v2d) { - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); - EditFace *efa; - MTFace *tface; + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tface; + MLoopUV *luv; short change= 0; - for(efa= em->faces.first; efa; efa= efa->next) { - tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(uvedit_face_visible(scene, ima, efa, tface)) { - if(uvedit_uv_selected(scene, efa, tface, 0)) VECCOPY2D(tface->uv[0], v2d->cursor); - if(uvedit_uv_selected(scene, efa, tface, 1)) VECCOPY2D(tface->uv[1], v2d->cursor); - if(uvedit_uv_selected(scene, efa, tface, 2)) VECCOPY2D(tface->uv[2], v2d->cursor); - if(efa->v4) - if(uvedit_uv_selected(scene, efa, tface, 3)) VECCOPY2D(tface->uv[3], v2d->cursor); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tface)) + continue; - change= 1; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if(uvedit_uv_selected(em, scene, l)) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + VECCOPY2D(luv->uv, v2d->cursor); + change= 1; + } } } - BKE_mesh_end_editmesh(obedit->data, em); return change; } static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obedit) { - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); - EditFace *efa; - EditVert *eve; - MTFace *tface; + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + BMVert *eve; + MTexPoly *tface; + MLoopUV *luv; short change = 0; int count = 0; float *coords; short *usercount, users; /* set all verts to -1 : an unused index*/ - for(eve= em->verts.first; eve; eve= eve->next) - eve->tmp.l=-1; + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) + BMINDEX_SET(eve, -1); /* index every vert that has a selected UV using it, but only once so as to * get unique indicies and to count how much to malloc */ - for(efa= em->faces.first; efa; efa= efa->next) { - tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - if(uvedit_face_visible(scene, ima, efa, tface)) { - if(uvedit_uv_selected(scene, efa, tface, 0) && efa->v1->tmp.l==-1) efa->v1->tmp.l= count++; - if(uvedit_uv_selected(scene, efa, tface, 1) && efa->v2->tmp.l==-1) efa->v2->tmp.l= count++; - if(uvedit_uv_selected(scene, efa, tface, 2) && efa->v3->tmp.l==-1) efa->v3->tmp.l= count++; - if(efa->v4) - if(uvedit_uv_selected(scene, efa, tface, 3) && efa->v4->tmp.l==-1) efa->v4->tmp.l= count++; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tface)) { + BMINDEX_SET(efa, 0); + continue; + } else { + BMINDEX_SET(efa, 1); + } - change = 1; - - /* optional speedup */ - efa->tmp.p = tface; + change = 1; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if (uvedit_uv_selected(em, scene, l) && BMINDEX_GET(l->v) == -1) { + BMINDEX_SET(l->v, count); + count++; + } } - else - efa->tmp.p = NULL; } coords = MEM_callocN(sizeof(float)*count*2, "snap to adjacent coords"); usercount = MEM_callocN(sizeof(short)*count, "snap to adjacent counts"); /* add all UV coords from visible, unselected UV coords as well as counting them to average later */ - for(efa= em->faces.first; efa; efa= efa->next) { - if((tface=(MTFace *)efa->tmp.p)) { - /* is this an unselected UV we can snap to? */ - if(efa->v1->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 0))) { - coords[efa->v1->tmp.l*2] += tface->uv[0][0]; - coords[(efa->v1->tmp.l*2)+1] += tface->uv[0][1]; - usercount[efa->v1->tmp.l]++; - change = 1; - } - if(efa->v2->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 1))) { - coords[efa->v2->tmp.l*2] += tface->uv[1][0]; - coords[(efa->v2->tmp.l*2)+1] += tface->uv[1][1]; - usercount[efa->v2->tmp.l]++; - change = 1; - } - if(efa->v3->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 2))) { - coords[efa->v3->tmp.l*2] += tface->uv[2][0]; - coords[(efa->v3->tmp.l*2)+1] += tface->uv[2][1]; - usercount[efa->v3->tmp.l]++; - change = 1; - } - - if(efa->v4) { - if(efa->v4->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 3))) { - coords[efa->v4->tmp.l*2] += tface->uv[3][0]; - coords[(efa->v4->tmp.l*2)+1] += tface->uv[3][1]; - usercount[efa->v4->tmp.l]++; - change = 1; - } + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BMINDEX_GET(efa)) + continue; + + tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tface)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if (BMINDEX_GET(l->v) >= 0 && + (!uvedit_uv_selected(em, scene, l))) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + coords[BMINDEX_GET(l->v)*2] += luv->uv[0]; + coords[BMINDEX_GET(l->v)*2+1] += luv->uv[1]; + change = 1; } } } @@ -2424,46 +2626,24 @@ static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obe if(!change) { MEM_freeN(coords); MEM_freeN(usercount); - BKE_mesh_end_editmesh(obedit->data, em); return change; } /* copy the averaged unselected UVs back to the selected UVs */ - for(efa= em->faces.first; efa; efa= efa->next) { - if((tface=(MTFace *)efa->tmp.p)) { - - if( uvedit_uv_selected(scene, efa, tface, 0) && - efa->v1->tmp.l >= 0 && - (users = usercount[efa->v1->tmp.l]) - ) { - tface->uv[0][0] = coords[efa->v1->tmp.l*2] / users; - tface->uv[0][1] = coords[(efa->v1->tmp.l*2)+1] / users; - } + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BMINDEX_GET(efa)) + continue; - if( uvedit_uv_selected(scene, efa, tface, 1) && - efa->v2->tmp.l >= 0 && - (users = usercount[efa->v2->tmp.l]) - ) { - tface->uv[1][0] = coords[efa->v2->tmp.l*2] / users; - tface->uv[1][1] = coords[(efa->v2->tmp.l*2)+1] / users; - } - - if( uvedit_uv_selected(scene, efa, tface, 2) && - efa->v3->tmp.l >= 0 && - (users = usercount[efa->v3->tmp.l]) - ) { - tface->uv[2][0] = coords[efa->v3->tmp.l*2] / users; - tface->uv[2][1] = coords[(efa->v3->tmp.l*2)+1] / users; - } - - if(efa->v4) { - if( uvedit_uv_selected(scene, efa, tface, 3) && - efa->v4->tmp.l >= 0 && - (users = usercount[efa->v4->tmp.l]) - ) { - tface->uv[3][0] = coords[efa->v4->tmp.l*2] / users; - tface->uv[3][1] = coords[(efa->v4->tmp.l*2)+1] / users; - } + tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tface)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if (uvedit_uv_selected(em, scene, l) && BMINDEX_GET(l->v) >= 0 + && (users = usercount[BMINDEX_GET(l->v)])) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv->uv[0] = coords[BMINDEX_GET(l->v)*2]; + luv->uv[1] = coords[BMINDEX_GET(l->v)*2+1]; } } } @@ -2471,43 +2651,41 @@ static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obe MEM_freeN(coords); MEM_freeN(usercount); - BKE_mesh_end_editmesh(obedit->data, em); return change; } static int snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit) { - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); - Image *ima; - EditFace *efa; - MTFace *tface; + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + Image *ima= sima->image; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tface; + MLoopUV *luv; int width= 0, height= 0; float w, h; short change = 0; - if(!sima) - return 0; - - ima= sima->image; - ED_space_image_size(sima, &width, &height); w = (float)width; h = (float)height; - for(efa= em->faces.first; efa; efa= efa->next) { - tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(uvedit_face_visible(scene, ima, efa, tface)) { - if(uvedit_uv_selected(scene, efa, tface, 0)) snap_uv_to_pixel(tface->uv[0], w, h); - if(uvedit_uv_selected(scene, efa, tface, 1)) snap_uv_to_pixel(tface->uv[1], w, h); - if(uvedit_uv_selected(scene, efa, tface, 2)) snap_uv_to_pixel(tface->uv[2], w, h); - if(efa->v4) - if(uvedit_uv_selected(scene, efa, tface, 3)) snap_uv_to_pixel(tface->uv[3], w, h); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tface)) + continue; - change = 1; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if (uvedit_uv_selected(em, scene, l)) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + snap_uv_to_pixel(luv->uv, w, h); + } } + + change = 1; } - BKE_mesh_end_editmesh(obedit->data, em); return change; } @@ -2569,35 +2747,34 @@ static int pin_exec(bContext *C, wmOperator *op) Scene *scene= CTX_data_scene(C); Object *obedit= CTX_data_edit_object(C); Image *ima= CTX_data_edit_image(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); - EditFace *efa; - MTFace *tface; + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tface; + MLoopUV *luv; int clear= RNA_boolean_get(op->ptr, "clear"); - for(efa= em->faces.first; efa; efa= efa->next) { - tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tface)) + continue; - if(uvedit_face_visible(scene, ima, efa, tface)) { + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + if(!clear) { - if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap |= TF_PIN1; - if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap |= TF_PIN2; - if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap |= TF_PIN3; - if(efa->v4) - if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap |= TF_PIN4; - } - else { - if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap &= ~TF_PIN1; - if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap &= ~TF_PIN2; - if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap &= ~TF_PIN3; - if(efa->v4) - if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap &= ~TF_PIN4; + if (uvedit_uv_selected(em, scene, l)) + luv->flag |= MLOOPUV_PINNED; + } else { + if (uvedit_uv_selected(em, scene, l)) + luv->flag &= ~MLOOPUV_PINNED; } } } WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -2623,26 +2800,28 @@ static int select_pinned_exec(bContext *C, wmOperator *op) Scene *scene= CTX_data_scene(C); Object *obedit= CTX_data_edit_object(C); Image *ima= CTX_data_edit_image(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); - EditFace *efa; - MTFace *tface; - - for(efa= em->faces.first; efa; efa= efa->next) { - tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - if(uvedit_face_visible(scene, ima, efa, tface)) { - if(tface->unwrap & TF_PIN1) uvedit_uv_select(scene, efa, tface, 0); - if(tface->unwrap & TF_PIN2) uvedit_uv_select(scene, efa, tface, 1); - if(tface->unwrap & TF_PIN3) uvedit_uv_select(scene, efa, tface, 2); - if(efa->v4) { - if(tface->unwrap & TF_PIN4) uvedit_uv_select(scene, efa, tface, 3); - } + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tface; + MLoopUV *luv; + + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if(!uvedit_face_visible(scene, ima, efa, tface)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + if (luv->flag & MLOOPUV_PINNED) + uvedit_uv_select(em, scene, l); } } WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -2665,125 +2844,51 @@ static int hide_exec(bContext *C, wmOperator *op) SpaceImage *sima= CTX_wm_space_image(C); ToolSettings *ts= CTX_data_tool_settings(C); Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); - EditFace *efa; - MTFace *tf; + Scene *scene = CTX_data_scene(C); + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; int swap= RNA_boolean_get(op->ptr, "unselected"); - int facemode= sima ? sima->flag & SI_SELACTFACE : 0; if(ts->uv_flag & UV_SYNC_SELECTION) { - EM_hide_mesh(em, swap); + EDBM_hide_mesh(em, swap); WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } - if(swap) { - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(facemode) { - /* Pretend face mode */ - if(( (efa->v4==NULL && - ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) == (TF_SEL1|TF_SEL2|TF_SEL3) ) || - ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) == (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) ) == 0) { - - if(em->selectmode == SCE_SELECT_FACE) { - efa->f &= ~SELECT; - /* must re-select after */ - efa->e1->f &= ~SELECT; - efa->e2->f &= ~SELECT; - efa->e3->f &= ~SELECT; - if(efa->e4) efa->e4->f &= ~SELECT; - } - else - EM_select_face(efa, 0); - } - tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); - } - else if(em->selectmode == SCE_SELECT_FACE) { - if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))==0) { - if(!efa->v4) - EM_select_face(efa, 0); - else if(!(tf->flag & TF_SEL4)) - EM_select_face(efa, 0); - tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); - } - } - else { - /* EM_deselect_flush will deselect the face */ - if((tf->flag & TF_SEL1)==0) efa->v1->f &= ~SELECT; - if((tf->flag & TF_SEL2)==0) efa->v2->f &= ~SELECT; - if((tf->flag & TF_SEL3)==0) efa->v3->f &= ~SELECT; - if((efa->v4) && (tf->flag & TF_SEL4)==0) efa->v4->f &= ~SELECT; - - tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); - } - } - } - } - else { - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - if(facemode) { - if( (efa->v4==NULL && - ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) == (TF_SEL1|TF_SEL2|TF_SEL3) ) || - ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) == (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) ) { - - if(em->selectmode == SCE_SELECT_FACE) { - efa->f &= ~SELECT; - /* must re-select after */ - efa->e1->f &= ~SELECT; - efa->e2->f &= ~SELECT; - efa->e3->f &= ~SELECT; - if(efa->e4) efa->e4->f &= ~SELECT; - } - else - EM_select_face(efa, 0); - } + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + int hide = 0; - tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); - } - else if(em->selectmode == SCE_SELECT_FACE) { - if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) - EM_select_face(efa, 0); - else if(efa->v4 && tf->flag & TF_SEL4) - EM_select_face(efa, 0); + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); - } - else { - /* EM_deselect_flush will deselect the face */ - if(tf->flag & TF_SEL1) efa->v1->f &= ~SELECT; - if(tf->flag & TF_SEL2) efa->v2->f &= ~SELECT; - if(tf->flag & TF_SEL3) efa->v3->f &= ~SELECT; - if((efa->v4) && tf->flag & TF_SEL4) efa->v4->f &= ~SELECT; - - tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); - } + if (luv->flag & MLOOPUV_VERTSEL) { + hide = 1; + break; } } + + if (swap) + hide = !hide; + + if (hide) { + BM_Select(em->bm, efa, 0); + uvedit_face_deselect(scene, em, efa); + } } - /*deselects too many but ok for now*/ - if(em->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX)) - EM_deselect_flush(em); + ///*deselects too many but ok for now*/ + //if(em->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX)) + // EM_deselect_flush(em); - if(em->selectmode==SCE_SELECT_FACE) { - /* de-selected all edges from faces that were de-selected. - * now make sure all faces that are selected also have selected edges */ - for(efa= em->faces.first; efa; efa= efa->next) - if(efa->f & SELECT) - EM_select_face(efa, 1); - } - EM_validate_selections(em); + EDBM_validate_selections(em); WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -2809,114 +2914,44 @@ static int reveal_exec(bContext *C, wmOperator *op) SpaceImage *sima= CTX_wm_space_image(C); ToolSettings *ts= CTX_data_tool_settings(C); Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); - EditFace *efa; - MTFace *tf; - int facemode= sima ? sima->flag & SI_SELACTFACE : 0; - int stickymode= sima ? (sima->sticky != SI_STICKY_DISABLE) : 1; + Scene *scene = CTX_data_scene(C); + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMVert *v; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; + BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + BMINDEX_SET(v, BM_TestHFlag(v, BM_SELECT)); + } + /* call the mesh function if we are in mesh sync sel */ if(ts->uv_flag & UV_SYNC_SELECTION) { - EM_reveal_mesh(em); + EDBM_reveal_mesh(em); WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } - - if(facemode) { - if(em->selectmode == SCE_SELECT_FACE) { - for(efa= em->faces.first; efa; efa= efa->next) { - if(!(efa->h) && !(efa->f & SELECT)) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - EM_select_face(efa, 1); - tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4; - } - } - } - else { - /* enable adjacent faces to have disconnected UV selections if sticky is disabled */ - if(!stickymode) { - for(efa= em->faces.first; efa; efa= efa->next) { - if(!(efa->h) && !(efa->f & SELECT)) { - /* All verts must be unselected for the face to be selected in the UV view */ - if((efa->v1->f&SELECT)==0 && (efa->v2->f&SELECT)==0 && (efa->v3->f&SELECT)==0 && (efa->v4==0 || (efa->v4->f&SELECT)==0)) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4; - /* Cant use EM_select_face here because it unselects the verts - * and we cant tell if the face was totally unselected or not */ - /*EM_select_face(efa, 1); - * - * See Loop with EM_select_face() below... */ - efa->f |= SELECT; - } - } - } - } - else { - for(efa= em->faces.first; efa; efa= efa->next) { - if(!(efa->h) && !(efa->f & SELECT)) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - if((efa->v1->f & SELECT)==0) {tf->flag |= TF_SEL1;} - if((efa->v2->f & SELECT)==0) {tf->flag |= TF_SEL2;} - if((efa->v3->f & SELECT)==0) {tf->flag |= TF_SEL3;} - if((efa->v4 && (efa->v4->f & SELECT)==0)) {tf->flag |= TF_SEL4;} - efa->f |= SELECT; - } + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (em->selectmode == SCE_SELECT_FACE) { + uvedit_face_select(scene, em, efa); + } else { + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if (!BMINDEX_GET(l->v)) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv->flag |= MLOOPUV_VERTSEL; } } - - /* Select all edges and verts now */ - for(efa= em->faces.first; efa; efa= efa->next) - /* we only selected the face flags, and didnt changes edges or verts, fix this now */ - if(!(efa->h) && (efa->f & SELECT)) - EM_select_face(efa, 1); - - EM_select_flush(em); - } - } - else if(em->selectmode == SCE_SELECT_FACE) { - for(efa= em->faces.first; efa; efa= efa->next) { - if(!(efa->h) && !(efa->f & SELECT)) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - efa->f |= SELECT; - tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4; - } } - - /* Select all edges and verts now */ - for(efa= em->faces.first; efa; efa= efa->next) - /* we only selected the face flags, and didnt changes edges or verts, fix this now */ - if(!(efa->h) && (efa->f & SELECT)) - EM_select_face(efa, 1); - } - else { - for(efa= em->faces.first; efa; efa= efa->next) { - if(!(efa->h) && !(efa->f & SELECT)) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - if((efa->v1->f & SELECT)==0) {tf->flag |= TF_SEL1;} - if((efa->v2->f & SELECT)==0) {tf->flag |= TF_SEL2;} - if((efa->v3->f & SELECT)==0) {tf->flag |= TF_SEL3;} - if((efa->v4 && (efa->v4->f & SELECT)==0)) {tf->flag |= TF_SEL4;} - efa->f |= SELECT; - } - } - - /* Select all edges and verts now */ - for(efa= em->faces.first; efa; efa= efa->next) - /* we only selected the face flags, and didnt changes edges or verts, fix this now */ - if(!(efa->h) && (efa->f & SELECT)) - EM_select_face(efa, 1); + BM_Select(em->bm, efa, 1); } WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index 20f74085e52..6d87b244736 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -727,8 +727,10 @@ static PEdge *p_edge_lookup(PHandle *handle, PHashKey *vkeys) return NULL; } -static PBool p_face_exists(PHandle *handle, PHashKey *vkeys, int i1, int i2, int i3) +int p_face_exists(ParamHandle *phandle, ParamKey *pvkeys, int i1, int i2, int i3) { + PHandle *handle = (PHandle*)phandle; + PHashKey *vkeys = (PHashKey*)pvkeys; PHashKey key = PHASH_edge(vkeys[i1], vkeys[i2]); PEdge *e = (PEdge*)phash_lookup(handle->hash_edges, key); diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.h b/source/blender/editors/uvedit/uvedit_parametrizer.h index f1454ee3865..8d440e2e652 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.h +++ b/source/blender/editors/uvedit/uvedit_parametrizer.h @@ -30,6 +30,8 @@ ParamHandle *param_construct_begin(); void param_aspect_ratio(ParamHandle *handle, float aspx, float aspy); +int p_face_exists(ParamHandle *handle, ParamKey *vkeys, int i1, int i2, int i3); + void param_face_add(ParamHandle *handle, ParamKey key, int nverts, diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index c7258e616fa..f1041603bed 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -47,10 +47,13 @@ #include "BKE_image.h" #include "BKE_mesh.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "BLI_arithb.h" #include "BLI_edgehash.h" #include "BLI_editVert.h" +#include "BLI_scanfill.h" +#include "BLI_array.h" #include "PIL_time.h" @@ -73,9 +76,9 @@ static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit) { - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); - EditFace *efa; - MTFace *tf; + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMIter iter; Image *ima; bScreen *sc; ScrArea *sa; @@ -83,15 +86,15 @@ static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit) SpaceImage *sima; if(ED_uvedit_test(obedit)) { - BKE_mesh_end_editmesh(obedit->data, em); return 1; } - if(em && em->faces.first) - EM_add_data_layer(em, &em->fdata, CD_MTFACE); - + if(em && em->bm->totface) {// && !CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY)) { + BM_add_data_layer(em->bm, &em->bm->pdata, CD_MTEXPOLY); + BM_add_data_layer(em->bm, &em->bm->ldata, CD_MLOOPUV); + } + if(!ED_uvedit_test(obedit)) { - BKE_mesh_end_editmesh(obedit->data, em); return 0; } @@ -121,33 +124,35 @@ static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit) ED_uvedit_assign_image(scene, obedit, ima, NULL); /* select new UV's */ - for(efa=em->faces.first; efa; efa=efa->next) { - tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - uvedit_face_select(scene, efa, tf); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + uvedit_face_select(scene, em, efa); } - BKE_mesh_end_editmesh(obedit->data, em); return 1; } /****************** Parametrizer Conversion ***************/ -ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short implicit, short fill, short sel, short correct_aspect) +ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em, + short implicit, short fill, short sel, + short correct_aspect) { ParamHandle *handle; - EditFace *efa; - EditEdge *eed; - EditVert *ev; - MTFace *tf; + BMFace *efa; + BMLoop *l; + BMEdge *eed; + BMVert *ev; + BMIter iter, liter; + MTexPoly *tf; int a; handle = param_construct_begin(); if(correct_aspect) { - efa = EM_get_actFace(em, 1); + efa = EDBM_get_actFace(em, 1); if(efa) { - MTFace *tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + MTexPoly *tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); float aspx, aspy; ED_image_uv_aspect(tf->tpage, &aspx, &aspy); @@ -158,71 +163,103 @@ ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short implicit, } /* we need the vert indicies */ - for(ev= em->verts.first, a=0; ev; ev= ev->next, a++) - ev->tmp.l = a; + a = 0; + BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + BMINDEX_SET(ev, a); + a++; + } - for(efa= em->faces.first; efa; efa= efa->next) { + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + EditVert *v, *lastv, *firstv; + EditFace *sefa; ParamKey key, vkeys[4]; ParamBool pin[4], select[4]; + BMLoop *ls[3]; + MLoopUV *luvs[3]; float *co[4]; float *uv[4]; - int nverts; + int lsel; - if((efa->h) || (sel && (efa->f & SELECT)==0)) + if((BM_TestHFlag(efa, BM_HIDDEN)) || (sel && BM_TestHFlag(efa, BM_SELECT)==0)) continue; - tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - if(implicit && - !( uvedit_uv_selected(scene, efa, tf, 0) || - uvedit_uv_selected(scene, efa, tf, 1) || - uvedit_uv_selected(scene, efa, tf, 2) || - (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) ) - ) { - continue; + tf= (MTexPoly *)CustomData_em_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + lsel = 0; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + if (uvedit_uv_selected(em, scene, l)) { + lsel = 1; + break; + } } + if (implicit && !lsel) + continue; + key = (ParamKey)efa; - vkeys[0] = (ParamKey)efa->v1->tmp.l; - vkeys[1] = (ParamKey)efa->v2->tmp.l; - vkeys[2] = (ParamKey)efa->v3->tmp.l; - - co[0] = efa->v1->co; - co[1] = efa->v2->co; - co[2] = efa->v3->co; - - uv[0] = tf->uv[0]; - uv[1] = tf->uv[1]; - uv[2] = tf->uv[2]; - - pin[0] = ((tf->unwrap & TF_PIN1) != 0); - pin[1] = ((tf->unwrap & TF_PIN2) != 0); - pin[2] = ((tf->unwrap & TF_PIN3) != 0); - - select[0] = ((uvedit_uv_selected(scene, efa, tf, 0)) != 0); - select[1] = ((uvedit_uv_selected(scene, efa, tf, 1)) != 0); - select[2] = ((uvedit_uv_selected(scene, efa, tf, 2)) != 0); - - if(efa->v4) { - vkeys[3] = (ParamKey)efa->v4->tmp.l; - co[3] = efa->v4->co; - uv[3] = tf->uv[3]; - pin[3] = ((tf->unwrap & TF_PIN4) != 0); - select[3] = (uvedit_uv_selected(scene, efa, tf, 3) != 0); - nverts = 4; + + /*scanfill time!*/ + firstv = lastv = NULL; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + v = BLI_addfillvert(l->v->co); + + v->tmp.p = l; + + if (lastv) { + BLI_addfilledge(lastv, v); + } + + lastv = v; + if (!firstv) + firstv = v; } - else - nverts = 3; - param_face_add(handle, key, nverts, vkeys, co, uv, pin, select); + BLI_addfilledge(firstv, v); + + /*mode 2 enables shortest-diagonal for quads*/ + BLI_edgefill(2, 0); + for (sefa = fillfacebase.first; sefa; sefa=sefa->next) { + ls[0] = sefa->v1->tmp.p; + ls[1] = sefa->v2->tmp.p; + ls[2] = sefa->v3->tmp.p; + + luvs[0] = CustomData_bmesh_get(&em->bm->ldata, ls[0]->head.data, CD_MLOOPUV); + luvs[1] = CustomData_bmesh_get(&em->bm->ldata, ls[1]->head.data, CD_MLOOPUV); + luvs[2] = CustomData_bmesh_get(&em->bm->ldata, ls[2]->head.data, CD_MLOOPUV); + + vkeys[0] = (ParamKey)BMINDEX_GET(ls[0]->v); + vkeys[1] = (ParamKey)BMINDEX_GET(ls[1]->v); + vkeys[2] = (ParamKey)BMINDEX_GET(ls[2]->v); + + co[0] = ls[0]->v->co; + co[1] = ls[1]->v->co; + co[2] = ls[2]->v->co; + + uv[0] = luvs[0]->uv; + uv[1] = luvs[1]->uv; + uv[2] = luvs[2]->uv; + + pin[0] = (luvs[0]->flag & MLOOPUV_PINNED) != 0; + pin[1] = (luvs[1]->flag & MLOOPUV_PINNED) != 0; + pin[2] = (luvs[2]->flag & MLOOPUV_PINNED) != 0; + + select[0] = uvedit_uv_selected(em, scene, ls[0]) != 0; + select[1] = uvedit_uv_selected(em, scene, ls[1]) != 0; + select[2] = uvedit_uv_selected(em, scene, ls[2]) != 0; + + if (!p_face_exists(handle,vkeys,0,1,2)) + param_face_add(handle, key, 3, vkeys, co, uv, pin, select); + } + + BLI_end_edgefill(); } if(!implicit) { - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->seam) { + BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) { + if(BM_TestHFlag(eed, BM_SEAM)) { ParamKey vkeys[2]; - vkeys[0] = (ParamKey)eed->v1->tmp.l; - vkeys[1] = (ParamKey)eed->v2->tmp.l; + vkeys[0] = (ParamKey)BMINDEX_GET(eed->v1); + vkeys[1] = (ParamKey)BMINDEX_GET(eed->v2); param_edge_set_seam(handle, vkeys); } } @@ -238,7 +275,7 @@ ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short implicit, typedef struct MinStretch { Scene *scene; Object *obedit; - EditMesh *em; + BMEditMesh *em; ParamHandle *handle; float blend; double lasttime; @@ -250,7 +287,7 @@ static void minimize_stretch_init(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); + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; MinStretch *ms; int fill_holes= RNA_boolean_get(op->ptr, "fill_holes"); @@ -433,7 +470,7 @@ static int pack_islands_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); + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; ParamHandle *handle; handle = construct_param_handle(scene, em, 1, 0, 1, 1); @@ -444,7 +481,6 @@ static int pack_islands_exec(bContext *C, wmOperator *op) DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -466,7 +502,7 @@ static int average_islands_scale_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); + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; ParamHandle *handle; handle= construct_param_handle(scene, em, 1, 0, 1, 1); @@ -477,7 +513,6 @@ static int average_islands_scale_exec(bContext *C, wmOperator *op) DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -499,19 +534,17 @@ static ParamHandle *liveHandle = NULL; void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit) { - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; short abf = scene->toolsettings->unwrapper == 1; short fillholes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES; if(!ED_uvedit_test(obedit)) { - BKE_mesh_end_editmesh(obedit->data, em); return; } - liveHandle = construct_param_handle(scene, em, 0, fillholes, 1, 1); + liveHandle = construct_param_handle(scene, em, 0, fillholes, 0, 1); param_lscm_begin(liveHandle, PARAM_TRUE, abf); - BKE_mesh_end_editmesh(obedit->data, em); } void ED_uvedit_live_unwrap_re_solve(void) @@ -542,9 +575,12 @@ void ED_uvedit_live_unwrap_end(short cancel) #define POLAR_ZX 0 #define POLAR_ZY 1 -static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, Object *ob, EditMesh *em) +static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, + Object *ob, BMEditMesh *em) { - EditFace *efa; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; float min[3], max[3], *cursx; int around= (v3d)? v3d->around: V3D_CENTER; @@ -554,13 +590,12 @@ static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, Ob case V3D_CENTER: /* bounding box center */ min[0]= min[1]= min[2]= 1e20f; max[0]= max[1]= max[2]= -1e20f; - - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - DO_MINMAX(efa->v1->co, min, max); - DO_MINMAX(efa->v2->co, min, max); - DO_MINMAX(efa->v3->co, min, max); - if(efa->v4) DO_MINMAX(efa->v4->co, min, max); + + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if(BM_TestHFlag(efa, BM_SELECT)) { + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + DO_MINMAX(l->v->co, min, max); + } } } VecMidf(result, min, max); @@ -634,7 +669,7 @@ static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float /* context checks are messy here, making it work in both 3d view and uv editor */ Scene *scene= CTX_data_scene(C); Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; View3D *v3d= CTX_wm_view3d(C); RegionView3D *rv3d= CTX_wm_region_view3d(C); /* common operator properties */ @@ -661,7 +696,6 @@ static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float else uv_map_rotation_matrix(rotmat, rv3d, obedit, upangledeg, sideangledeg, radius); - BKE_mesh_end_editmesh(obedit->data, em); } static void uv_transform_properties(wmOperatorType *ot, int radius) @@ -684,14 +718,17 @@ static void uv_transform_properties(wmOperatorType *ot, int radius) RNA_def_float(ot->srna, "radius", 1.0f, 0.0f, FLT_MAX, "Radius", "Radius of the sphere or cylinder.", 0.0001f, 100.0f); } -static void correct_uv_aspect(EditMesh *em) +static void correct_uv_aspect(BMEditMesh *em) { - EditFace *efa= EM_get_actFace(em, 1); - MTFace *tf; + BMFace *efa= EDBM_get_actFace(em, 1); + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; float scale, aspx= 1.0f, aspy=1.0f; if(efa) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); ED_image_uv_aspect(tf->tpage, &aspx, &aspy); } @@ -701,30 +738,28 @@ static void correct_uv_aspect(EditMesh *em) if(aspx > aspy) { scale= aspy/aspx; - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - tf->uv[0][0]= ((tf->uv[0][0]-0.5)*scale)+0.5; - tf->uv[1][0]= ((tf->uv[1][0]-0.5)*scale)+0.5; - tf->uv[2][0]= ((tf->uv[2][0]-0.5)*scale)+0.5; - if(efa->v4) - tf->uv[3][0]= ((tf->uv[3][0]-0.5)*scale)+0.5; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if (!BM_TestHFlag(efa, BM_SELECT)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv->uv[0] = ((luv->uv[0]-0.5)*scale)+0.5; } } } else { scale= aspx/aspy; - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - tf->uv[0][1]= ((tf->uv[0][1]-0.5)*scale)+0.5; - tf->uv[1][1]= ((tf->uv[1][1]-0.5)*scale)+0.5; - tf->uv[2][1]= ((tf->uv[2][1]-0.5)*scale)+0.5; - if(efa->v4) - tf->uv[3][1]= ((tf->uv[3][1]-0.5)*scale)+0.5; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if (!BM_TestHFlag(efa, BM_SELECT)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv->uv[1] = ((luv->uv[1]-0.5)*scale)+0.5; } } } @@ -739,10 +774,12 @@ static void uv_map_clip_correct_properties(wmOperatorType *ot) RNA_def_boolean(ot->srna, "scale_to_bounds", 0, "Scale to Bounds", "Scale UV coordinates to bounds after unwrapping."); } -static void uv_map_clip_correct(EditMesh *em, wmOperator *op) +static void uv_map_clip_correct(BMEditMesh *em, wmOperator *op) { - EditFace *efa; - MTFace *tf; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; float dx, dy, min[2], max[2]; int b, nverts; int correct_aspect= RNA_boolean_get(op->ptr, "correct_aspect"); @@ -756,16 +793,13 @@ static void uv_map_clip_correct(EditMesh *em, wmOperator *op) if(scale_to_bounds) { INIT_MINMAX2(min, max); - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BM_TestHFlag(efa, BM_SELECT)) + continue; - DO_MINMAX2(tf->uv[0], min, max); - DO_MINMAX2(tf->uv[1], min, max); - DO_MINMAX2(tf->uv[2], min, max); - - if(efa->v4) - DO_MINMAX2(tf->uv[3], min, max); + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + DO_MINMAX2(luv->uv, min, max); } } @@ -778,31 +812,28 @@ static void uv_map_clip_correct(EditMesh *em, wmOperator *op) if(dy > 0.0f) dy= 1.0f/dy; - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - nverts= (efa->v4)? 4: 3; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BM_TestHFlag(efa, BM_SELECT)) + continue; - for(b=0; b<nverts; b++) { - tf->uv[b][0]= (tf->uv[b][0]-min[0])*dx; - tf->uv[b][1]= (tf->uv[b][1]-min[1])*dy; - } + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + luv->uv[0] = (luv->uv[0]-min[0])*dx; + luv->uv[1] = (luv->uv[1]-min[1])*dy; } } } else if(clip_to_bounds) { /* clipping and wrapping */ - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - nverts= (efa->v4)? 4: 3; - - for(b=0; b<nverts; b++) { - CLAMP(tf->uv[b][0], 0.0, 1.0); - CLAMP(tf->uv[b][1], 0.0, 1.0); - } + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BM_TestHFlag(efa, BM_SELECT)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + CLAMP(luv->uv[0], 0.0, 1.0); + CLAMP(luv->uv[1], 0.0, 1.0); } } } @@ -814,7 +845,7 @@ static int unwrap_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); + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; ParamHandle *handle; int method = RNA_enum_get(op->ptr, "method"); int fill_holes = RNA_boolean_get(op->ptr, "fill_holes"); @@ -822,7 +853,6 @@ static int unwrap_exec(bContext *C, wmOperator *op) /* add uvs if they don't exist yet */ if(!ED_uvedit_ensure_uvs(C, scene, obedit)) { - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED; } @@ -841,7 +871,6 @@ static int unwrap_exec(bContext *C, wmOperator *op) DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -926,45 +955,42 @@ static int from_view_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); + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; ARegion *ar= CTX_wm_region(C); - EditFace *efa; - MTFace *tf; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; float rotmat[4][4]; /* add uvs if they don't exist yet */ if(!ED_uvedit_ensure_uvs(C, scene, obedit)) { - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED; } if(RNA_boolean_get(op->ptr, "orthographic")) { uv_map_rotation_matrix(rotmat, ar->regiondata, obedit, 90.0f, 0.0f, 1.0f); - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - uv_from_view_bounds(tf->uv[0], efa->v1->co, rotmat); - uv_from_view_bounds(tf->uv[1], efa->v2->co, rotmat); - uv_from_view_bounds(tf->uv[2], efa->v3->co, rotmat); - if(efa->v4) - uv_from_view_bounds(tf->uv[3], efa->v4->co, rotmat); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BM_TestHFlag(efa, BM_SELECT)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + uv_from_view_bounds(luv->uv, l->v->co, rotmat); } } } else { Mat4CpyMat4(rotmat, obedit->obmat); - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BM_TestHFlag(efa, BM_SELECT)) + continue; - uv_from_view(ar, tf->uv[0], efa->v1->co, rotmat); - uv_from_view(ar, tf->uv[1], efa->v2->co, rotmat); - uv_from_view(ar, tf->uv[2], efa->v3->co, rotmat); - if(efa->v4) - uv_from_view(ar, tf->uv[3], efa->v4->co, rotmat); + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + uv_from_view(ar, luv->uv, l->v->co, rotmat); } } } @@ -974,7 +1000,6 @@ static int from_view_exec(bContext *C, wmOperator *op) DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -1010,38 +1035,75 @@ static int reset_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); - EditFace *efa; - MTFace *tf; + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; + BLI_array_declare(uvs); + float **uvs = NULL; + int i; /* add uvs if they don't exist yet */ if(!ED_uvedit_ensure_uvs(C, scene, obedit)) { - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED; } - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BM_TestHFlag(efa, BM_SELECT)) + continue; + + BLI_array_empty(uvs); + i = 0; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + BLI_array_growone(uvs); - tf->uv[0][0]= 0.0f; - tf->uv[0][1]= 0.0f; - - tf->uv[1][0]= 1.0f; - tf->uv[1][1]= 0.0f; + uvs[i++] = luv->uv; + } + + if (i == 3) { + uvs[0][0] = 0.0; + uvs[0][1] = 0.0; - tf->uv[2][0]= 1.0f; - tf->uv[2][1]= 1.0f; + uvs[1][0] = 1.0; + uvs[1][1] = 0.0; + + uvs[2][0] = 1.0; + uvs[2][1] = 1.0; + } else if (i == 4) { + uvs[0][0] = 0.0; + uvs[0][1] = 0.0; - tf->uv[3][0]= 0.0f; - tf->uv[3][1]= 1.0f; + uvs[1][0] = 1.0; + uvs[1][1] = 0.0; + + uvs[2][0] = 1.0; + uvs[2][1] = 1.0; + + uvs[3][0] = 0.0; + uvs[3][1] = 1.0; + /*make sure we ignore 2-sided faces*/ + } else if (i > 2) { + float fac = 0.0f, dfac = 1.0f / (float)efa->len; + + dfac *= M_PI*2; + + for (i=0; i<efa->len; i++) { + uvs[i][0] = sin(fac); + uvs[i][1] = cos(fac); + + fac += dfac; + } } } DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + BLI_array_free(uvs); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -1073,55 +1135,71 @@ static void uv_sphere_project(float target[2], float source[3], float center[3], target[0] -= 1.0f; } -static void uv_map_mirror(EditFace *efa, MTFace *tf) +static void uv_map_mirror(BMEditMesh *em, BMFace *efa, MTexPoly *tf) { + BMLoop *l; + BMIter liter; + MLoopUV *luv; + BLI_array_declare(uvs); + float **uvs = NULL; float dx; - int nverts, i, mi; + int i, mi; - nverts= (efa->v4)? 4: 3; + i = 0; + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + BLI_array_growone(uvs); + + uvs[i] = luv->uv; + i++; + } mi = 0; - for(i=1; i<nverts; i++) - if(tf->uv[i][0] > tf->uv[mi][0]) + for(i=1; i<efa->len; i++) + if(uvs[i][0] > uvs[mi][0]) mi = i; - for(i=0; i<nverts; i++) { + for(i=0; i<efa->len; i++) { if(i != mi) { - dx = tf->uv[mi][0] - tf->uv[i][0]; - if(dx > 0.5) tf->uv[i][0] += 1.0; + dx = uvs[mi][0] - uvs[i][0]; + if(dx > 0.5) uvs[i][0] += 1.0; } } + + BLI_array_free(uvs); } static int sphere_project_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); - EditFace *efa; - MTFace *tf; + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; float center[3], rotmat[4][4]; /* add uvs if they don't exist yet */ if(!ED_uvedit_ensure_uvs(C, scene, obedit)) { - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED; } uv_map_transform(C, op, center, rotmat); - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + if (!BM_TestHFlag(efa, BM_SELECT)) + continue; - uv_sphere_project(tf->uv[0], efa->v1->co, center, rotmat); - uv_sphere_project(tf->uv[1], efa->v2->co, center, rotmat); - uv_sphere_project(tf->uv[2], efa->v3->co, center, rotmat); - if(efa->v4) - uv_sphere_project(tf->uv[3], efa->v4->co, center, rotmat); + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - uv_map_mirror(efa, tf); + uv_sphere_project(luv->uv, l->v->co, center, rotmat); } + + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + uv_map_mirror(em, efa, tf); } uv_map_clip_correct(em, op); @@ -1129,7 +1207,6 @@ static int sphere_project_exec(bContext *C, wmOperator *op) DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -1169,31 +1246,33 @@ static int cylinder_project_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); - EditFace *efa; - MTFace *tf; + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; float center[3], rotmat[4][4]; /* add uvs if they don't exist yet */ if(!ED_uvedit_ensure_uvs(C, scene, obedit)) { - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED; } uv_map_transform(C, op, center, rotmat); - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - uv_cylinder_project(tf->uv[0], efa->v1->co, center, rotmat); - uv_cylinder_project(tf->uv[1], efa->v2->co, center, rotmat); - uv_cylinder_project(tf->uv[2], efa->v3->co, center, rotmat); - if(efa->v4) - uv_cylinder_project(tf->uv[3], efa->v4->co, center, rotmat); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if (!BM_TestHFlag(efa, BM_SELECT)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - uv_map_mirror(efa, tf); + uv_cylinder_project(luv->uv, l->v->co, center, rotmat); } + + uv_map_mirror(em, efa, tf); } uv_map_clip_correct(em, op); @@ -1201,7 +1280,6 @@ static int cylinder_project_exec(bContext *C, wmOperator *op) DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } @@ -1227,15 +1305,17 @@ static int cube_project_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); - EditFace *efa; - MTFace *tf; + BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MTexPoly *tf; + MLoopUV *luv; float no[3], cube_size, *loc, dx, dy; int cox, coy; /* add uvs if they don't exist yet */ if(!ED_uvedit_ensure_uvs(C, scene, obedit)) { - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_CANCELLED; } @@ -1245,41 +1325,38 @@ static int cube_project_exec(bContext *C, wmOperator *op) /* choose x,y,z axis for projection depending on the largest normal * component, but clusters all together around the center of map. */ - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, no); - - no[0]= fabs(no[0]); - no[1]= fabs(no[1]); - no[2]= fabs(no[2]); - - cox=0; coy= 1; - if(no[2]>=no[0] && no[2]>=no[1]); - else if(no[1]>=no[0] && no[1]>=no[2]) coy= 2; - else { cox= 1; coy= 2; } + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + int first=1; + + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if (!BM_TestHFlag(efa, BM_SELECT)) + continue; + + VECCOPY(no, efa->no); + + no[0]= fabs(no[0]); + no[1]= fabs(no[1]); + no[2]= fabs(no[2]); + + cox=0; coy= 1; + if(no[2]>=no[0] && no[2]>=no[1]); + else if(no[1]>=no[0] && no[1]>=no[2]) coy= 2; + else { cox= 1; coy= 2; } + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + luv->uv[0] = 0.5+0.5*cube_size*(loc[cox] + l->v->co[cox]); + luv->uv[1] = 0.5+0.5*cube_size*(loc[coy] + l->v->co[coy]); - tf->uv[0][0]= 0.5+0.5*cube_size*(loc[cox] + efa->v1->co[cox]); - tf->uv[0][1]= 0.5+0.5*cube_size*(loc[coy] + efa->v1->co[coy]); - dx = floor(tf->uv[0][0]); - dy = floor(tf->uv[0][1]); - tf->uv[0][0] -= dx; - tf->uv[0][1] -= dy; - tf->uv[1][0]= 0.5+0.5*cube_size*(loc[cox] + efa->v2->co[cox]); - tf->uv[1][1]= 0.5+0.5*cube_size*(loc[coy] + efa->v2->co[coy]); - tf->uv[1][0] -= dx; - tf->uv[1][1] -= dy; - tf->uv[2][0]= 0.5+0.5*cube_size*(loc[cox] + efa->v3->co[cox]); - tf->uv[2][1]= 0.5+0.5*cube_size*(loc[coy] + efa->v3->co[coy]); - tf->uv[2][0] -= dx; - tf->uv[2][1] -= dy; - - if(efa->v4) { - tf->uv[3][0]= 0.5+0.5*cube_size*(loc[cox] + efa->v4->co[cox]); - tf->uv[3][1]= 0.5+0.5*cube_size*(loc[coy] + efa->v4->co[coy]); - tf->uv[3][0] -= dx; - tf->uv[3][1] -= dy; + if (first) { + dx = floor(luv->uv[0]); + dy = floor(luv->uv[1]); + first = 0; } + + luv->uv[0] -= dx; + luv->uv[1] -= dy; } } @@ -1288,7 +1365,6 @@ static int cube_project_exec(bContext *C, wmOperator *op) DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - BKE_mesh_end_editmesh(obedit->data, em); return OPERATOR_FINISHED; } |