2009-05-18 10:29:37 +00:00
/* $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"
2009-09-17 23:05:33 +00:00
# include "BLI_array.h"
2009-05-18 10:29:37 +00:00
# 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"
2009-07-16 06:27:37 +00:00
# include "ED_transform.h"
2009-05-18 10:29:37 +00:00
# include "UI_interface.h"
# include "mesh_intern.h"
# include "bmesh.h"
2009-10-07 21:19:58 +00:00
# include "editbmesh_bvh.h"
2009-05-18 14:55:34 +00:00
static void add_normal_aligned ( float * nor , float * add )
{
if ( INPR ( nor , add ) < - 0.9999f )
VecSubf ( nor , nor , add ) ;
else
VecAddf ( nor , nor , add ) ;
}
2009-07-16 06:27:37 +00:00
static int subdivide_exec ( bContext * C , wmOperator * op )
{
2009-09-16 17:43:09 +00:00
ToolSettings * ts = CTX_data_tool_settings ( C ) ;
2009-07-16 06:27:37 +00:00
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 ;
2009-08-11 11:33:23 +00:00
BM_esubdivideflag ( obedit , em - > bm , BM_SELECT ,
smooth , fractal ,
2009-09-16 17:43:09 +00:00
ts - > editbutflag | flag ,
2009-08-11 11:33:23 +00:00
cuts , 0 , RNA_enum_get ( op - > ptr , " quadcorner " ) ,
RNA_boolean_get ( op - > ptr , " tess_single_edge " ) ,
RNA_boolean_get ( op - > ptr , " gridfill " ) ) ;
2009-07-16 06:27:37 +00:00
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-07-16 06:27:37 +00:00
return OPERATOR_FINISHED ;
}
2009-08-11 11:33:23 +00:00
/* 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 }
} ;
2009-07-16 06:27:37 +00:00
void MESH_OT_subdivide ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Subdivide " ;
2009-08-26 10:27:04 +00:00
ot - > description = " Subdivide selected edges. " ;
2009-07-16 06:27:37 +00:00
ot - > idname = " MESH_OT_subdivide " ;
/* api callbacks */
ot - > exec = subdivide_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* properties */
bmeshafied vertex smooth, and also added a 'repeat' option :) since the last operator panel works after this last 2.5 merge, yayscons/scons.py BF_QUICK=bf_python,bf_blenkernel,bf_blenlib,bf_blenloader,bf_editors_mesh,bf_bmesh,bf_editors_space_view3d,bf_editors_transform,bf_makesdna,bf_makesrna,bf_dna,bf_rn,bf_bmesh,bf_editors_object,editors_uvedit,editors_space_image,editors_screen,editors_space_screen
2009-08-06 11:27:08 +00:00
RNA_def_int ( ot - > srna , " number_cuts " , 1 , 1 , 20 , " Number of Cuts " , " " , 1 , INT_MAX ) ;
2009-07-16 06:27:37 +00:00
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 ) ;
2009-05-18 10:29:37 +00:00
/*props */
2009-08-15 17:31:28 +00:00
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 " ) ;
2009-08-11 11:33:23 +00:00
RNA_def_boolean ( ot - > srna , " gridfill " , 1 , " Grid Fill " , " Fill Fully Selected Triangles and Quads With A Grid " ) ;
2009-05-18 10:29:37 +00:00
}
2009-05-18 14:55:34 +00:00
/* individual face extrude */
/* will use vertex normals for extrusion directions, so *nor is unaffected */
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
short EDBM_Extrude_face_indiv ( BMEditMesh * em , wmOperator * op , short flag , float * nor )
2009-05-18 14:55:34 +00:00
{
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
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
}
2009-05-18 14:55:34 +00:00
#if 0
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
short EDBM_Extrude_face_indiv ( BMEditMesh * em , wmOperator * op , short flag , float * nor )
2009-05-18 14:55:34 +00:00
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 ' ;
}
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
# endif
2009-05-18 14:55:34 +00:00
/* extrudes individual edges */
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
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
2009-05-18 14:55:34 +00:00
/* 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
}
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
# endif
2009-05-18 14:55:34 +00:00
/* extrudes individual vertices */
2009-05-19 00:33:54 +00:00
short EDBM_Extrude_verts_indiv ( BMEditMesh * em , wmOperator * op , short flag , float * nor )
2009-05-18 14:55:34 +00:00
{
2009-05-28 04:41:02 +00:00
BMOperator bmop ;
EDBM_InitOpf ( em , & bmop , op , " extrude_vert_indiv verts=%hv " , flag ) ;
/*deselect original verts*/
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
BMO_UnHeaderFlag_Buffer ( em - > bm , & bmop , " verts " , BM_SELECT , BM_VERT ) ;
2009-05-19 00:33:54 +00:00
2009-05-28 04:41:02 +00:00
BMO_Exec_Op ( em - > bm , & bmop ) ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
BMO_HeaderFlag_Buffer ( em - > bm , & bmop , " vertout " , BM_SELECT , BM_VERT ) ;
2009-05-28 04:41:02 +00:00
if ( ! EDBM_FinishOp ( em , & bmop , op , 1 ) ) return 0 ;
2009-05-18 14:55:34 +00:00
2009-05-28 04:41:02 +00:00
return ' g ' ; // g is grab
2009-05-18 14:55:34 +00:00
}
2009-06-02 07:40:32 +00:00
short EDBM_Extrude_edge ( Object * obedit , BMEditMesh * em , int flag , float * nor )
2009-05-18 14:55:34 +00:00
{
BMesh * bm = em - > bm ;
BMIter iter ;
BMOIter siter ;
BMOperator extop ;
2009-05-28 04:41:02 +00:00
BMVert * vert ;
2009-05-18 14:55:34 +00:00
BMEdge * edge ;
BMFace * f ;
ModifierData * md ;
2009-06-02 07:40:32 +00:00
BMHeader * el ;
2009-05-18 14:55:34 +00:00
BMO_Init_Op ( & extop , " extrudefaceregion " ) ;
BMO_HeaderFlag_To_Slot ( bm , & extop , " edgefacein " ,
flag , BM_VERT | BM_EDGE | BM_FACE ) ;
2009-05-28 04:41:02 +00:00
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 ) ;
2009-05-18 14:55:34 +00:00
}
2009-05-28 04:41:02 +00:00
BM_ITER ( f , & iter , bm , BM_FACES_OF_MESH , NULL ) {
BM_Select ( bm , f , 0 ) ;
2009-05-18 14:55:34 +00:00
}
/* 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 ) ;
2009-06-02 07:40:32 +00:00
nor [ 0 ] = nor [ 1 ] = nor [ 2 ] = 0.0f ;
2009-06-23 05:35:49 +00:00
BMO_ITER ( el , & siter , bm , & extop , " geomout " , BM_ALL ) {
2009-05-18 14:55:34 +00:00
BM_Select ( bm , el , 1 ) ;
2009-06-02 07:40:32 +00:00
if ( el - > type = = BM_FACE ) {
f = ( BMFace * ) el ;
add_normal_aligned ( nor , f - > no ) ;
} ;
2009-05-18 14:55:34 +00:00
}
2009-06-02 07:40:32 +00:00
Normalize ( nor ) ;
2009-05-18 14:55:34 +00:00
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 ) ) {
2009-05-19 00:33:54 +00:00
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 ) ;
}
2009-05-18 14:55:34 +00:00
} else {
2009-05-19 00:33:54 +00:00
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 ) ;
}
2009-05-18 14:55:34 +00:00
}
}
return EDBM_Extrude_edge ( obedit , em , flag , nor ) ;
2009-06-02 07:40:32 +00:00
}
2009-05-18 14:55:34 +00:00
static int extrude_repeat_mesh ( bContext * C , wmOperator * op )
{
Object * obedit = CTX_data_edit_object ( C ) ;
2009-06-12 14:02:37 +00:00
Scene * scene = CTX_data_scene ( C ) ;
2009-06-02 07:40:32 +00:00
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
2009-05-18 14:55:34 +00:00
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 + + ) {
2009-06-02 07:40:32 +00:00
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);
2009-05-18 14:55:34 +00:00
}
2009-06-02 07:40:32 +00:00
EDBM_RecalcNormals ( em ) ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-05-18 14:55:34 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_extrude_repeat ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Extrude Repeat Mesh " ;
2009-08-26 10:27:04 +00:00
ot - > description = " Extrude selected vertices, edges or faces repeatedly. " ;
2009-05-18 14:55:34 +00:00
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 */
2009-07-16 06:27:37 +00:00
int EDBM_Extrude_Mesh ( Object * obedit , BMEditMesh * em , wmOperator * op , float * norin )
2009-05-18 14:55:34 +00:00
{
Scene * scene = NULL ; // XXX CTX!
short nr , transmode = 0 ;
2009-07-16 06:27:37 +00:00
float stacknor [ 3 ] = { 0.0f , 0.0f , 0.0f } ;
float * nor = norin ? norin : stacknor ;
2009-05-18 14:55:34 +00:00
2009-07-16 06:27:37 +00:00
nor [ 0 ] = nor [ 1 ] = nor [ 2 ] = 0.0f ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
2009-05-18 14:55:34 +00:00
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");
}
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
2009-07-16 06:27:37 +00:00
if ( nr < 1 ) return ' g ' ;
2009-05-18 14:55:34 +00:00
2009-06-02 07:40:32 +00:00
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 ) ;
2009-05-19 00:33:54 +00:00
else if ( nr = = 4 ) transmode = EDBM_Extrude_verts_indiv ( em , op , SELECT , nor ) ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
else if ( nr = = 3 ) transmode = EDBM_Extrude_edges_indiv ( em , op , SELECT , nor ) ;
else transmode = EDBM_Extrude_face_indiv ( em , op , SELECT , nor ) ;
2009-05-18 14:55:34 +00:00
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();
}
}
2009-07-16 06:27:37 +00:00
return transmode ;
2009-05-18 14:55:34 +00:00
}
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
/* 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 ) ;
2009-09-16 17:43:09 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_SELECT , obedit ) ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
return OPERATOR_FINISHED ;
}
static int mesh_extrude_region_invoke ( bContext * C , wmOperator * op , wmEvent * event )
2009-05-18 14:55:34 +00:00
{
2009-07-16 06:27:37 +00:00
Scene * scene = CTX_data_scene ( C ) ;
2009-05-18 14:55:34 +00:00
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
float nor [ 3 ] ;
2009-07-16 06:27:37 +00:00
int constraint_axis [ 3 ] = { 0 , 0 , 1 } ;
int tmode ;
2009-05-18 14:55:34 +00:00
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
tmode = EDBM_Extrude_edge ( obedit , em , BM_SELECT , nor ) ;
2009-05-18 14:55:34 +00:00
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-07-16 06:27:37 +00:00
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 ) ;
}
2009-07-22 02:57:40 +00:00
WM_operator_name_call ( C , " TFM_OT_translate " , WM_OP_INVOKE_REGION_WIN , op - > ptr ) ;
2009-07-16 06:27:37 +00:00
return OPERATOR_FINISHED ;
2009-05-18 14:55:34 +00:00
}
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
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 )
2009-05-18 14:55:34 +00:00
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
float nor [ 3 ] ;
EDBM_Extrude_verts_indiv ( em , op , BM_SELECT , nor ) ;
2009-05-18 14:55:34 +00:00
2009-09-16 17:43:09 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_SELECT , obedit ) ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
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 ) ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
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 ) ;
2009-05-18 14:55:34 +00:00
2009-09-16 17:43:09 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_SELECT , obedit ) ;
2009-05-18 14:55:34 +00:00
return OPERATOR_FINISHED ;
}
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
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 ) ;
2009-05-18 14:55:34 +00:00
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
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 )
2009-05-18 14:55:34 +00:00
{
/* identifiers */
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
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 ) ;
2009-09-16 17:43:09 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_SELECT , obedit ) ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
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 ) ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
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 " ;
2009-05-18 14:55:34 +00:00
/* api callbacks */
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
ot - > invoke = mesh_extrude_faces_invoke ;
ot - > exec = mesh_extrude_faces_exec ;
2009-05-18 14:55:34 +00:00
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* to give to transform */
2009-07-16 06:27:37 +00:00
Properties_Proportional ( ot ) ;
Properties_Constraints ( ot ) ;
RNA_def_boolean ( ot - > srna , " mirror " , 0 , " Mirror Editing " , " " ) ;
2009-05-18 14:55:34 +00:00
}
2009-05-28 04:41:02 +00:00
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
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 " ;
2009-08-26 10:27:04 +00:00
ot - > description = " Extrude selected vertices, edges or faces. " ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
ot - > idname = " MESH_OT_extrude " ;
/* api callbacks */
ot - > invoke = extrude_menu_invoke ;
ot - > poll = ED_operator_editmesh ;
}
2009-05-28 04:41:02 +00:00
/* ******************** (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 ) ;
2009-09-16 17:43:09 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_SELECT , obedit ) ;
2009-05-28 04:41:02 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_select_all_toggle ( wmOperatorType * ot )
{
/* identifiers */
2009-07-16 06:27:37 +00:00
ot - > name = " Select/Deselect All " ;
2009-05-28 04:41:02 +00:00
ot - > idname = " MESH_OT_select_all_toggle " ;
2009-08-26 10:27:04 +00:00
ot - > description = " (de)select all vertices, edges or faces. " ;
2009-05-28 04:41:02 +00:00
/* api callbacks */
ot - > exec = toggle_select_all_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
2009-06-02 07:40:32 +00:00
/* *************** add-click-mesh (extrude) operator ************** */
static int dupli_extrude_cursor ( bContext * C , wmOperator * op , wmEvent * event )
{
ViewContext vc ;
2009-07-26 14:58:31 +00:00
BMVert * v1 ;
2009-06-18 02:05:56 +00:00
BMIter iter ;
2009-06-02 07:40:32 +00:00
float min [ 3 ] , max [ 3 ] ;
int done = 0 ;
em_setup_viewcontext ( C , & vc ) ;
INIT_MINMAX ( min , max ) ;
2009-08-05 06:06:58 +00:00
BM_ITER_SELECT ( v1 , & iter , vc . em - > bm , BM_VERTS_OF_MESH , NULL )
DO_MINMAX ( v1 - > co , min , max ) ;
done = 1 ;
2009-06-02 07:40:32 +00:00
}
/* call extrude? */
if ( done ) {
2009-06-18 02:05:56 +00:00
BMEdge * eed ;
2009-06-02 07:40:32 +00:00
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 ;
2009-06-18 02:05:56 +00:00
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 ) ;
2009-06-02 07:40:32 +00:00
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 ) ;
}
}
2009-06-18 02:05:56 +00:00
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 ) ;
2009-06-02 07:40:32 +00:00
}
else {
float * curs = give_cursor ( vc . scene , vc . v3d ) ;
2009-06-18 03:04:27 +00:00
BMOperator bmop ;
BMOIter oiter ;
2009-06-02 07:40:32 +00:00
VECCOPY ( min , curs ) ;
2009-06-18 03:04:27 +00:00
2009-06-02 07:40:32 +00:00
view3d_get_view_aligned_coordinate ( & vc , min , event - > mval ) ;
2009-06-18 03:04:27 +00:00
Mat4Invert ( vc . obedit - > imat , vc . obedit - > obmat ) ;
Mat4MulVecfl ( vc . obedit - > imat , min ) ; // back in object space
2009-06-02 07:40:32 +00:00
2009-06-18 03:04:27 +00:00
EDBM_InitOpf ( vc . em , & bmop , op , " makevert co=%v " , min ) ;
BMO_Exec_Op ( vc . em - > bm , & bmop ) ;
2009-06-02 07:40:32 +00:00
2009-06-23 05:35:49 +00:00
BMO_ITER ( v1 , & oiter , vc . em - > bm , & bmop , " newvertout " , BM_VERT ) {
2009-06-18 03:04:27 +00:00
BM_Select ( vc . em - > bm , v1 , 1 ) ;
}
if ( ! EDBM_FinishOp ( vc . em , & bmop , op , 1 ) )
return OPERATOR_CANCELLED ;
2009-06-02 07:40:32 +00:00
}
2009-06-18 02:05:56 +00:00
2009-06-02 07:40:32 +00:00
//retopo_do_all();
2009-09-16 17:43:09 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , vc . obedit - > data ) ;
DAG_id_flush_update ( vc . obedit - > data , OB_RECALC_DATA ) ;
2009-06-02 07:40:32 +00:00
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 ;
2009-08-26 10:27:04 +00:00
ot - > description = " Duplicate and extrude selected vertices, edges or faces towards the mouse cursor. " ;
2009-06-02 07:40:32 +00:00
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
2009-06-18 01:31:50 +00:00
2009-09-16 17:43:09 +00:00
static int delete_mesh ( bContext * C , Object * obedit , wmOperator * op , int event , Scene * scene )
2009-06-18 01:31:50 +00:00
{
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 ;
}
2009-06-23 05:35:49 +00:00
else if ( event = = 11 ) {
//"Edge Loop"
if ( ! EDBM_CallOpf ( bem , op , " dissolveedgeloop edges=%he " , BM_SELECT ) )
return OPERATOR_CANCELLED ;
}
2009-06-18 01:31:50 +00:00
else if ( event = = 7 ) {
2009-06-18 04:39:33 +00:00
//"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 ;
}
2009-06-18 01:31:50 +00:00
}
else if ( event = = 4 ) {
2009-07-16 06:27:37 +00:00
//Edges and Faces
2009-06-18 01:31:50 +00:00
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 ;
}
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-06-18 01:31:50 +00:00
return OPERATOR_FINISHED ;
}
/* Note, these values must match delete_mesh() event values */
static EnumPropertyItem prop_mesh_delete_types [ ] = {
2009-07-16 06:27:37 +00:00
{ 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 }
2009-06-18 01:31:50 +00:00
} ;
static int delete_mesh_exec ( bContext * C , wmOperator * op )
{
Object * obedit = CTX_data_edit_object ( C ) ;
Scene * scene = CTX_data_scene ( C ) ;
2009-09-16 17:43:09 +00:00
delete_mesh ( C , obedit , op , RNA_enum_get ( op - > ptr , " type " ) , scene ) ;
2009-06-18 01:31:50 +00:00
2009-09-16 17:43:09 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA | ND_SELECT , obedit ) ;
2009-06-18 01:31:50 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_delete ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Delete " ;
2009-08-26 10:27:04 +00:00
ot - > description = " Delete selected vertices, edges or faces. " ;
2009-06-18 01:31:50 +00:00
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 ) ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
BMO_HeaderFlag_Buffer ( em - > bm , & bmop , " faceout " , BM_SELECT , BM_FACE ) ;
2009-06-18 01:31:50 +00:00
if ( ! EDBM_FinishOp ( em , & bmop , op , 1 ) )
return OPERATOR_CANCELLED ;
2009-09-16 17:43:09 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_SELECT , obedit ) ;
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-06-18 01:31:50 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_edge_face_add ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Make Edge/Face " ;
2009-08-26 10:27:04 +00:00
ot - > description = " Add an edge or face to selected. " ;
2009-06-18 01:31:50 +00:00
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 ;
}
2009-06-18 10:15:23 +00:00
static EnumPropertyItem prop_mesh_edit_types [ ] = {
2009-07-16 06:27:37 +00:00
{ 1 , " VERT " , 0 , " Vertices " , " " } ,
{ 2 , " EDGE " , 0 , " Edges " , " " } ,
{ 3 , " FACE " , 0 , " Faces " , " " } ,
{ 0 , NULL , 0 , NULL , NULL }
2009-06-18 10:15:23 +00:00
} ;
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 ) ;
2009-09-16 17:43:09 +00:00
CTX_data_tool_settings ( C ) - > selectmode = em - > selectmode ;
2009-06-18 10:15:23 +00:00
2009-09-16 17:43:09 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_SELECT , obedit ) ;
2009-06-18 10:15:23 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_selection_type ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Selection Mode " ;
2009-08-26 10:27:04 +00:00
ot - > description = " Set the selection mode type. " ;
2009-06-18 10:15:23 +00:00
ot - > idname = " MESH_OT_selection_type " ;
/* api callbacks */
2009-06-23 05:35:49 +00:00
ot - > invoke = WM_menu_invoke ;
2009-06-18 10:15:23 +00:00
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 " ) ;
}
2009-07-16 06:27:37 +00:00
/* ************************* 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 ) {
2009-08-05 06:06:58 +00:00
BM_ITER_SELECT ( eed , & iter , bm , BM_EDGES_OF_MESH , NULL )
BM_ClearHFlag ( eed , BM_SEAM ) ;
2009-07-16 06:27:37 +00:00
}
}
else {
2009-08-05 06:06:58 +00:00
BM_ITER_SELECT ( eed , & iter , bm , BM_EDGES_OF_MESH , NULL )
BM_SetHFlag ( eed , BM_SEAM ) ;
2009-07-16 06:27:37 +00:00
}
}
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-07-16 06:27:37 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_mark_seam ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Mark Seam " ;
ot - > idname = " MESH_OT_mark_seam " ;
2009-08-26 10:27:04 +00:00
ot - > description = " (un)mark selected edges as a seam. " ;
2009-07-16 06:27:37 +00:00
/* 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 ) {
2009-08-05 06:06:58 +00:00
BM_ITER_SELECT ( eed , & iter , bm , BM_EDGES_OF_MESH , NULL )
BM_SetHFlag ( eed , BM_SHARP ) ;
2009-07-16 06:27:37 +00:00
}
} else {
2009-08-05 06:06:58 +00:00
BM_ITER_SELECT ( eed , & iter , bm , BM_EDGES_OF_MESH , NULL )
BM_ClearHFlag ( eed , BM_SHARP ) ;
2009-07-16 06:27:37 +00:00
}
}
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-07-16 06:27:37 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_mark_sharp ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Mark Sharp " ;
ot - > idname = " MESH_OT_mark_sharp " ;
2009-08-26 10:27:04 +00:00
ot - > description = " (un)mark selected edges as sharp. " ;
2009-07-16 06:27:37 +00:00
/* 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 " , " " ) ;
}
2009-07-17 05:09:33 +00:00
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 ) ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-07-17 05:09:33 +00:00
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 ;
}
2009-07-17 06:05:09 +00:00
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 ) ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-07-17 06:05:09 +00:00
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 ) ;
}
2009-07-21 08:39:58 +00:00
/****************** 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 ) ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
BMO_HeaderFlag_Buffer ( em - > bm , & bmop , " newout " , BM_SELECT , BM_ALL ) ;
2009-07-21 08:39:58 +00:00
if ( ! EDBM_FinishOp ( em , & bmop , op , 1 ) )
return OPERATOR_CANCELLED ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( ob - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , ob - > data ) ;
2009-07-21 08:39:58 +00:00
return OPERATOR_FINISHED ;
}
static int mesh_duplicate_invoke ( bContext * C , wmOperator * op , wmEvent * event )
{
WM_cursor_wait ( 1 ) ;
2009-08-06 09:56:14 +00:00
mesh_duplicate_exec ( C , op ) ;
2009-07-21 08:39:58 +00:00
WM_cursor_wait ( 0 ) ;
return OPERATOR_FINISHED ;
}
void MESH_OT_duplicate ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Duplicate " ;
2009-08-26 10:27:04 +00:00
ot - > description = " Duplicate selected vertices, edges or faces. " ;
2009-07-21 08:39:58 +00:00
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 ) ;
}
2009-07-22 02:57:40 +00:00
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 ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-07-22 02:57:40 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_flip_normals ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Flip Normals " ;
2009-08-26 10:27:04 +00:00
ot - > description = " Flip the direction of selected face's vertex and face normals " ;
2009-07-22 02:57:40 +00:00
ot - > idname = " MESH_OT_flip_normals " ;
/* api callbacks */
ot - > exec = flip_normals ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
2009-09-02 20:26:12 +00:00
//#define DIRECTION_CW 1
//#define DIRECTION_CCW 2
2009-07-26 14:58:31 +00:00
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 ) {
2009-08-05 06:06:58 +00:00
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 ) ) )
{
2009-07-26 14:58:31 +00:00
break ;
2009-08-05 06:06:58 +00:00
}
2009-07-26 14:58:31 +00:00
}
}
/*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 ) {
2009-08-05 06:06:58 +00:00
BM_ITER_SELECT ( eed , & iter , em - > bm , BM_EDGES_OF_MESH , NULL )
2009-07-26 14:58:31 +00:00
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 ) ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
BMO_HeaderFlag_Buffer ( em - > bm , & bmop , " edgeout " , BM_SELECT , BM_EDGE ) ;
2009-07-26 14:58:31 +00:00
if ( ! EDBM_FinishOp ( em , & bmop , op , 1 ) )
return OPERATOR_CANCELLED ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-07-26 14:58:31 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_edge_rotate ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Rotate Selected Edge " ;
2009-08-26 10:27:04 +00:00
ot - > description = " Rotate selected edge or adjoining faces. " ;
2009-07-26 14:58:31 +00:00
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. " ) ;
}
2009-08-05 06:06:58 +00:00
2009-09-10 03:59:12 +00:00
/* 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 " ) ) ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-09-10 03:59:12 +00:00
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 " ) ) ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-09-10 03:59:12 +00:00
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. " ) ;
}
2009-08-05 06:06:58 +00:00
/* 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 " ) ) ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-08-05 06:06:58 +00:00
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 ;
2009-08-26 10:27:04 +00:00
ot - > description = " Hide (un)selected vertices, edges or faces. " ;
2009-08-05 06:06:58 +00:00
/* 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 ) ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-08-05 06:06:58 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_reveal ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Reveal Hidden " ;
ot - > idname = " MESH_OT_reveal " ;
2009-08-26 10:27:04 +00:00
ot - > description = " Reveal all hidden vertices, edges and faces. " ;
2009-08-05 06:06:58 +00:00
/* api callbacks */
ot - > exec = reveal_mesh_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
2009-08-06 08:23:10 +00:00
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 ) ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-08-06 08:23:10 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_normals_make_consistent ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Make Normals Consistent " ;
2009-08-26 10:27:04 +00:00
ot - > description = " Make face and vertex normals point either outside or inside the mesh " ;
2009-08-06 08:23:10 +00:00
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 " , " " ) ;
}
bmeshafied vertex smooth, and also added a 'repeat' option :) since the last operator panel works after this last 2.5 merge, yayscons/scons.py BF_QUICK=bf_python,bf_blenkernel,bf_blenlib,bf_blenloader,bf_editors_mesh,bf_bmesh,bf_editors_space_view3d,bf_editors_transform,bf_makesdna,bf_makesrna,bf_dna,bf_rn,bf_bmesh,bf_editors_object,editors_uvedit,editors_space_image,editors_screen,editors_space_screen
2009-08-06 11:27:08 +00:00
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.
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
bmeshafied vertex smooth, and also added a 'repeat' option :) since the last operator panel works after this last 2.5 merge, yayscons/scons.py BF_QUICK=bf_python,bf_blenkernel,bf_blenlib,bf_blenloader,bf_editors_mesh,bf_bmesh,bf_editors_space_view3d,bf_editors_transform,bf_makesdna,bf_makesrna,bf_dna,bf_rn,bf_bmesh,bf_editors_object,editors_uvedit,editors_space_image,editors_screen,editors_space_screen
2009-08-06 11:27:08 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_vertices_smooth ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Smooth Vertex " ;
2009-08-26 10:27:04 +00:00
ot - > description = " Flatten angles of selected vertices. " ;
bmeshafied vertex smooth, and also added a 'repeat' option :) since the last operator panel works after this last 2.5 merge, yayscons/scons.py BF_QUICK=bf_python,bf_blenkernel,bf_blenlib,bf_blenloader,bf_editors_mesh,bf_bmesh,bf_editors_space_view3d,bf_editors_transform,bf_makesdna,bf_makesrna,bf_dna,bf_rn,bf_bmesh,bf_editors_object,editors_uvedit,editors_space_image,editors_screen,editors_space_screen
2009-08-06 11:27:08 +00:00
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 ;
2009-08-06 14:03:43 +00:00
RNA_def_int ( ot - > srna , " repeat " , 1 , 1 , 100 , " Number of times to smooth the mesh " , " " , 1 , INT_MAX ) ;
bmeshafied vertex smooth, and also added a 'repeat' option :) since the last operator panel works after this last 2.5 merge, yayscons/scons.py BF_QUICK=bf_python,bf_blenkernel,bf_blenlib,bf_blenloader,bf_editors_mesh,bf_bmesh,bf_editors_space_view3d,bf_editors_transform,bf_makesdna,bf_makesrna,bf_dna,bf_rn,bf_bmesh,bf_editors_object,editors_uvedit,editors_space_image,editors_screen,editors_space_screen
2009-08-06 11:27:08 +00:00
}
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
static int bm_test_exec ( bContext * C , wmOperator * op )
{
Scene * scene = CTX_data_scene ( C ) ;
Object * obedit = CTX_data_edit_object ( C ) ;
2009-10-07 21:19:58 +00:00
RegionView3D * r3d = CTX_wm_region_view3d ( C ) ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
2009-10-07 21:19:58 +00:00
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 ) ;
}
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
2009-10-07 21:19:58 +00:00
BMBVH_FreeBVH ( tree ) ;
#if 0 //uv island walker test
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
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
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
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);
}
subsurf works now! YES! take *that* subsurf_ccg.cscons/scons.py BF_QUICK=bf_python,bf_blenkernel,bf_blenlib,bf_blenloader,bf_editors_mesh,bf_bmesh,bf_editors_space_view3d,bf_editors_transform,bf_makesdna,bf_makesrna,bf_dna,bf_rn,bf_bmesh,bf_editors_object,editors_uvedit,editors_space_image,editors_screen,editors_space_screen,editors_space_api,bf_windowmanager,bf_wm still an issue with some modifier combinations though, and I think there's some memory corruption going on, need to valgrind it.
2009-08-25 10:21:10 +00:00
/********************** 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 ) ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
subsurf works now! YES! take *that* subsurf_ccg.cscons/scons.py BF_QUICK=bf_python,bf_blenkernel,bf_blenlib,bf_blenloader,bf_editors_mesh,bf_bmesh,bf_editors_space_view3d,bf_editors_transform,bf_makesdna,bf_makesrna,bf_dna,bf_rn,bf_bmesh,bf_editors_object,editors_uvedit,editors_space_image,editors_screen,editors_space_screen,editors_space_api,bf_windowmanager,bf_wm still an issue with some modifier combinations though, and I think there's some memory corruption going on, need to valgrind it.
2009-08-25 10:21:10 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_faces_shade_smooth ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Shade Smooth " ;
2009-08-26 10:27:04 +00:00
ot - > description = " Display faces smooth (using vertex normals). " ;
subsurf works now! YES! take *that* subsurf_ccg.cscons/scons.py BF_QUICK=bf_python,bf_blenkernel,bf_blenlib,bf_blenloader,bf_editors_mesh,bf_bmesh,bf_editors_space_view3d,bf_editors_transform,bf_makesdna,bf_makesrna,bf_dna,bf_rn,bf_bmesh,bf_editors_object,editors_uvedit,editors_space_image,editors_screen,editors_space_screen,editors_space_api,bf_windowmanager,bf_wm still an issue with some modifier combinations though, and I think there's some memory corruption going on, need to valgrind it.
2009-08-25 10:21:10 +00:00
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 ) ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
subsurf works now! YES! take *that* subsurf_ccg.cscons/scons.py BF_QUICK=bf_python,bf_blenkernel,bf_blenlib,bf_blenloader,bf_editors_mesh,bf_bmesh,bf_editors_space_view3d,bf_editors_transform,bf_makesdna,bf_makesrna,bf_dna,bf_rn,bf_bmesh,bf_editors_object,editors_uvedit,editors_space_image,editors_screen,editors_space_screen,editors_space_api,bf_windowmanager,bf_wm still an issue with some modifier combinations though, and I think there's some memory corruption going on, need to valgrind it.
2009-08-25 10:21:10 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_faces_shade_flat ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Shade Flat " ;
2009-08-26 10:27:04 +00:00
ot - > description = " Display faces flat. " ;
subsurf works now! YES! take *that* subsurf_ccg.cscons/scons.py BF_QUICK=bf_python,bf_blenkernel,bf_blenlib,bf_blenloader,bf_editors_mesh,bf_bmesh,bf_editors_space_view3d,bf_editors_transform,bf_makesdna,bf_makesrna,bf_dna,bf_rn,bf_bmesh,bf_editors_object,editors_uvedit,editors_space_image,editors_screen,editors_space_screen,editors_space_api,bf_windowmanager,bf_wm still an issue with some modifier combinations though, and I think there's some memory corruption going on, need to valgrind it.
2009-08-25 10:21:10 +00:00
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 ;
}
2009-08-28 10:17:31 +00:00
/********************** UV/Color Operators *************************/
2009-09-02 20:26:12 +00:00
2009-08-28 10:17:31 +00:00
static const EnumPropertyItem axis_items [ ] = {
2009-09-02 20:26:12 +00:00
{ OPUVC_AXIS_X , " X " , 0 , " X " , " " } ,
{ OPUVC_AXIS_Y , " Y " , 0 , " Y " , " " } ,
2009-08-28 10:17:31 +00:00
{ 0 , NULL , 0 , NULL , NULL } } ;
static int mesh_rotate_uvs ( bContext * C , wmOperator * op )
{
2009-09-02 20:26:12 +00:00
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 */
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( ob - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , ob - > data ) ;
2009-09-20 18:18:40 +00:00
/* DAG_id_flush_update(ob->data, OB_RECALC_DATA);
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , ob - > data ) ;
*/
2009-09-02 20:26:12 +00:00
/* we succeeded */
return OPERATOR_FINISHED ;
2009-08-28 10:17:31 +00:00
}
2009-09-12 07:08:57 +00:00
static int mesh_reverse_uvs ( bContext * C , wmOperator * op )
2009-08-28 10:17:31 +00:00
{
2009-09-12 07:08:57 +00:00
Scene * scene = CTX_data_scene ( C ) ;
Object * ob = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) ob - > data ) - > edit_btmesh ;
BMOperator bmop ;
2009-08-28 10:17:31 +00:00
2009-09-12 07:08:57 +00:00
/* 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 ) ;
2009-08-28 10:17:31 +00:00
2009-09-12 07:08:57 +00:00
/* execute the operator */
BMO_Exec_Op ( em - > bm , & bmop ) ;
2009-08-28 10:17:31 +00:00
2009-09-12 07:08:57 +00:00
/* finish the operator */
if ( ! EDBM_FinishOp ( em , & bmop , op , 1 ) )
2009-08-28 10:17:31 +00:00
return OPERATOR_CANCELLED ;
2009-09-12 07:08:57 +00:00
/* dependencies graph and notification stuff */
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( ob - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , ob - > data ) ;
2009-09-20 18:18:40 +00:00
/* DAG_id_flush_update(ob->data, OB_RECALC_DATA);
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , ob - > data ) ;
*/
2009-09-12 07:08:57 +00:00
/* we succeeded */
2009-08-28 10:17:31 +00:00
return OPERATOR_FINISHED ;
}
static int mesh_rotate_colors ( bContext * C , wmOperator * op )
{
2009-09-20 18:18:40 +00:00
Scene * scene = CTX_data_scene ( C ) ;
Object * ob = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) ob - > data ) - > edit_btmesh ;
BMOperator bmop ;
2009-08-28 10:17:31 +00:00
2009-09-20 18:18:40 +00:00
/* get the direction from RNA */
int dir = RNA_enum_get ( op - > ptr , " direction " ) ;
2009-08-28 10:17:31 +00:00
2009-09-20 18:18:40 +00:00
/* 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 ) ;
2009-08-28 10:17:31 +00:00
2009-09-20 18:18:40 +00:00
/* execute the operator */
BMO_Exec_Op ( em - > bm , & bmop ) ;
2009-08-28 10:17:31 +00:00
2009-09-20 18:18:40 +00:00
/* finish the operator */
if ( ! EDBM_FinishOp ( em , & bmop , op , 1 ) )
2009-08-28 10:17:31 +00:00
return OPERATOR_CANCELLED ;
2009-09-20 18:18:40 +00:00
/* 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 */
2009-08-28 10:17:31 +00:00
return OPERATOR_FINISHED ;
}
2009-09-20 18:18:40 +00:00
static int mesh_reverse_colors ( bContext * C , wmOperator * op )
2009-08-28 10:17:31 +00:00
{
2009-09-20 18:18:40 +00:00
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 ;
2009-08-28 10:17:31 +00:00
#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 ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-08-28 10:17:31 +00:00
# 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. " ) ;
}
2009-09-12 07:08:57 +00:00
//void MESH_OT_uvs_mirror(wmOperatorType *ot)
void MESH_OT_uvs_reverse ( wmOperatorType * ot )
2009-08-28 10:17:31 +00:00
{
/* identifiers */
2009-09-12 07:08:57 +00:00
ot - > name = " Reverse UVs " ;
ot - > idname = " MESH_OT_uvs_reverse " ;
2009-08-28 10:17:31 +00:00
/* api callbacks */
2009-09-12 07:08:57 +00:00
ot - > exec = mesh_reverse_uvs ;
2009-08-28 10:17:31 +00:00
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* props */
2009-09-12 07:08:57 +00:00
//RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror UVs around.");
2009-08-28 10:17:31 +00:00
}
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. " ) ;
}
2009-09-20 18:18:40 +00:00
void MESH_OT_colors_reverse ( wmOperatorType * ot )
2009-08-28 10:17:31 +00:00
{
/* identifiers */
2009-09-20 18:18:40 +00:00
ot - > name = " Reverse Colors " ;
ot - > idname = " MESH_OT_colors_reverse " ;
2009-08-28 10:17:31 +00:00
/* api callbacks */
2009-09-20 18:18:40 +00:00
ot - > exec = mesh_reverse_colors ;
2009-08-28 10:17:31 +00:00
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* props */
2009-09-20 18:18:40 +00:00
//RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around.");
2009-08-28 10:17:31 +00:00
}
2009-08-31 23:07:05 +00:00
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 ;
}
2009-09-12 04:03:26 +00:00
static int merge_target ( BMEditMesh * em , Scene * scene , View3D * v3d , Object * ob ,
2009-08-31 23:07:05 +00:00
int target , int uvmerge , wmOperator * wmop )
{
BMIter iter ;
BMVert * v ;
2009-09-12 04:03:26 +00:00
float * vco , co [ 3 ] , cent [ 3 ] = { 0.0f , 0.0f , 0.0f } , fac ;
2009-08-31 23:07:05 +00:00
int i ;
if ( target ) {
2009-09-12 04:03:26 +00:00
vco = give_cursor ( scene , v3d ) ;
VECCOPY ( co , vco ) ;
Mat4MulVecfl ( ob - > imat , co ) ;
2009-08-31 23:07:05 +00:00
} 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 ) ;
2009-09-12 04:03:26 +00:00
VECCOPY ( co , cent ) ;
2009-08-31 23:07:05 +00:00
}
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 :
2009-09-12 04:03:26 +00:00
status = merge_target ( em , scene , v3d , obedit , 0 , uvs , op ) ;
2009-08-31 23:07:05 +00:00
break ;
case 4 :
2009-09-12 04:03:26 +00:00
status = merge_target ( em , scene , v3d , obedit , 1 , uvs , op ) ;
2009-08-31 23:07:05 +00:00
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 ;
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-08-31 23:07:05 +00:00
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 ) ;
2009-09-01 16:05:33 +00:00
RNA_def_boolean ( ot - > srna , " uvs " , 1 , " UVs " , " Move UVs according to merge. " ) ;
2009-08-31 23:07:05 +00:00
}
2009-09-09 06:28:58 +00:00
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 ) ;
}
*/
2009-09-16 17:43:09 +00:00
DAG_id_flush_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2009-09-09 06:28:58 +00:00
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 ;
2009-10-22 23:22:05 +00:00
RNA_def_float ( ot - > srna , " mergedist " , 0.0001f , 0.000001f , 50.0f ,
2009-09-09 06:28:58 +00:00
" Merge Distance " ,
" Minimum distance between elements to merge. " , 0.00001 , 10.0 ) ;
}
2009-09-20 18:18:40 +00:00
/************************ 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. " ) ;
}
2009-10-07 21:19:58 +00:00
/********************** 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 ) ;
}
2009-10-22 23:22:05 +00:00
/*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*/
2009-10-24 05:43:27 +00:00
BM_ITER ( v , & iter , em - > bm , BM_VERTS_OF_MESH , NULL ) {
2009-10-22 23:22:05 +00:00
if ( BM_TestHFlag ( v , BM_SELECT ) )
break ;
2009-10-24 05:43:27 +00:00
}
2009-10-22 23:22:05 +00:00
/*this should be impossible, but sanity checks are a good thing*/
if ( ! v )
return OPERATOR_CANCELLED ;
/*find closest edge to mouse cursor*/
2009-10-07 21:19:58 +00:00
e2 = NULL ;
2009-10-22 23:22:05 +00:00
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 ;
2009-10-07 21:19:58 +00:00
e2 = e ;
}
}
2009-10-22 23:22:05 +00:00
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 ) ;
}
2009-10-07 21:19:58 +00:00
}
}
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 " , " " ) ;
}