2011-10-24 23:32:24 +00:00
/*
2009-05-18 10:29:37 +00:00
* * * * * * 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 "RNA_types.h"
# include "RNA_define.h"
# include "RNA_access.h"
2011-05-09 04:06:48 +00:00
# include "BLI_utildefines.h"
2009-05-18 10:29:37 +00:00
# include "BLI_blenlib.h"
2009-11-23 14:41:22 +00:00
# include "BLI_math.h"
2009-05-18 10:29:37 +00:00
# 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"
2011-05-01 20:43:54 +00:00
# include "BLI_smallhash.h"
2009-05-18 10:29:37 +00:00
2010-10-03 21:10:59 +00:00
# include "BKE_material.h"
2009-05-18 10:29:37 +00:00
# include "BKE_context.h"
# include "BKE_customdata.h"
2011-05-02 00:58:33 +00:00
# include "BKE_DerivedMesh.h"
# include "BKE_cdderivedmesh.h"
2009-05-18 10:29:37 +00:00
# include "BKE_depsgraph.h"
# include "BKE_global.h"
# include "BKE_library.h"
# include "BKE_mesh.h"
# include "BKE_object.h"
# include "BKE_bmesh.h"
# include "BKE_report.h"
# include "BKE_tessmesh.h"
2011-02-27 06:19:40 +00:00
# include "BKE_texture.h"
2010-10-03 21:10:59 +00:00
# include "BKE_main.h"
2009-05-18 10:29:37 +00:00
# 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"
2010-10-03 21:10:59 +00:00
# include "ED_object.h"
2009-05-18 10:29:37 +00:00
# include "UI_interface.h"
2011-02-27 06:19:40 +00:00
# include "RE_render_ext.h"
2009-05-18 10:29:37 +00:00
# include "mesh_intern.h"
# include "bmesh.h"
2009-10-07 21:19:58 +00:00
# include "editbmesh_bvh.h"
2011-11-16 17:37:20 +00:00
static void add_normal_aligned ( float nor [ 3 ] , const float add [ 3 ] )
2009-05-18 14:55:34 +00:00
{
2011-11-16 17:37:20 +00:00
if ( dot_v3v3 ( nor , add ) < - 0.9999f )
sub_v3_v3 ( nor , add ) ;
2009-05-18 14:55:34 +00:00
else
2011-11-16 17:37:20 +00:00
sub_v3_v3 ( nor , add ) ;
2009-05-18 14:55:34 +00:00
}
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 " ) ;
2011-11-01 04:31:25 +00:00
float smooth = 0.292f * RNA_float_get ( op - > ptr , " smoothness " ) ;
2011-03-28 00:29:45 +00:00
float fractal = RNA_float_get ( op - > ptr , " fractal " ) / 2.5 ;
2009-07-16 06:27:37 +00:00
int flag = 0 ;
2011-11-01 04:31:25 +00:00
if ( smooth ! = 0.0f )
flag | = B_SMOOTH ;
2009-07-16 06:27:37 +00:00
if ( fractal ! = 0.0f )
flag | = B_FRACTAL ;
2011-03-28 00:29:45 +00:00
if ( RNA_boolean_get ( op - > ptr , " quadtri " ) & &
RNA_enum_get ( op - > ptr , " quadcorner " ) = = SUBD_STRAIGHT_CUT )
{
RNA_enum_set ( op - > ptr , " quadcorner " , SUBD_INNERVERT ) ;
}
2009-08-11 11:33:23 +00:00
BM_esubdivideflag ( obedit , em - > bm , BM_SELECT ,
2011-11-01 04:31:25 +00:00
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 " ) ,
2011-03-28 00:29:45 +00:00
RNA_boolean_get ( op - > ptr , " quadtri " ) ,
1 , RNA_int_get ( op - > ptr , " seed " ) ) ;
2009-07-16 06:27:37 +00:00
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 " ;
2011-09-23 13:31:48 +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 */
2011-09-07 12:06:08 +00:00
RNA_def_int ( ot - > srna , " number_cuts " , 1 , 1 , INT_MAX , " Number of Cuts " , " " , 1 , 10 ) ;
2011-10-26 07:41:56 +00:00
/* BMESH_TODO, this currently does nothing, just add to stop UI from erroring out! */
RNA_def_float ( ot - > srna , " smoothness " , 0.0f , 0.0f , FLT_MAX , " Smoothness " , " Smoothness factor (BMESH TODO) " , 0.0f , 1.0f ) ;
2009-05-18 10:29:37 +00:00
2011-03-28 00:29:45 +00:00
RNA_def_boolean ( ot - > srna , " quadtri " , 0 , " Quad/Tri Mode " , " Tries to prevent ngons " ) ;
RNA_def_enum ( ot - > srna , " quadcorner " , prop_mesh_cornervert_types , SUBD_STRAIGHT_CUT , " Quad Corner Type " , " How to subdivide quad corners (anything other then Straight Cut will prevent ngons) " ) ;
2011-10-12 06:11:21 +00:00
RNA_def_float ( ot - > srna , " fractal " , 0.0f , 0.0f , FLT_MAX , " Fractal " , " Fractal randomness factor " , 0.0f , 1000.0f ) ;
2011-03-28 00:29:45 +00:00
RNA_def_int ( ot - > srna , " seed " , 0 , 0 , 10000 , " Random Seed " , " Seed for the random number generator " , 0 , 50 ) ;
2009-05-18 10:29:37 +00:00
}
2011-05-11 14:05:22 +00:00
void EMBM_project_snap_verts ( bContext * C , ARegion * ar , Object * obedit , BMEditMesh * em )
{
BMIter iter ;
BMVert * eve ;
BM_ITER ( eve , & iter , em - > bm , BM_VERTS_OF_MESH , NULL ) {
if ( BM_TestHFlag ( eve , BM_SELECT ) ) {
float mval [ 2 ] , vec [ 3 ] , no_dummy [ 3 ] ;
int dist_dummy ;
mul_v3_m4v3 ( vec , obedit - > obmat , eve - > co ) ;
project_float_noclip ( ar , vec , mval ) ;
if ( snapObjectsContext ( C , mval , & dist_dummy , vec , no_dummy , SNAP_NOT_OBEDIT ) ) {
mul_v3_m4v3 ( eve - > co , obedit - > imat , vec ) ;
}
}
}
}
2009-05-18 14:55:34 +00:00
/* individual face extrude */
/* will use vertex normals for extrusion directions, so *nor is unaffected */
2011-11-01 14:36:23 +00:00
static short EDBM_Extrude_face_indiv ( BMEditMesh * em , wmOperator * op , const char hflag , float * UNUSED ( 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 ;
2011-11-01 14:36:23 +00:00
EDBM_InitOpf ( em , & bmop , op , " extrude_face_indiv faces=%hf " , hflag ) ;
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
/*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 ) {
2011-09-12 05:51:35 +00:00
copy_v3_v3 ( l - > v - > no , f - > no ) ;
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
}
}
if ( ! EDBM_FinishOp ( em , & bmop , op , 1 ) ) return 0 ;
return ' s ' ; // s is shrink/fatten
}
2009-05-18 14:55:34 +00:00
/* extrudes individual edges */
2011-11-01 14:36:23 +00:00
static short EDBM_Extrude_edges_indiv ( BMEditMesh * em , wmOperator * op , const char hflag , float * UNUSED ( 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
{
BMOperator bmop ;
2011-11-01 14:36:23 +00:00
EDBM_InitOpf ( em , & bmop , op , " extrude_edge_only edges=%he " , hflag ) ;
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
/*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
}
2009-05-18 14:55:34 +00:00
/* extrudes individual vertices */
2011-11-01 14:36:23 +00:00
static short EDBM_Extrude_verts_indiv ( BMEditMesh * em , wmOperator * op , const char hflag , float * UNUSED ( nor ) )
2009-05-18 14:55:34 +00:00
{
2009-05-28 04:41:02 +00:00
BMOperator bmop ;
2011-11-01 14:36:23 +00:00
EDBM_InitOpf ( em , & bmop , op , " extrude_vert_indiv verts=%hv " , hflag ) ;
2009-05-28 04:41:02 +00:00
/*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
}
2011-11-01 14:36:23 +00:00
static short EDBM_Extrude_edge ( Object * obedit , BMEditMesh * em , const char hflag , float * nor )
2009-05-18 14:55:34 +00:00
{
BMesh * bm = em - > bm ;
BMIter iter ;
BMOIter siter ;
BMOperator extop ;
BMEdge * edge ;
BMFace * f ;
ModifierData * md ;
2009-06-02 07:40:32 +00:00
BMHeader * el ;
2009-05-18 14:55:34 +00:00
2011-11-16 14:36:23 +00:00
BMO_Init_Op ( bm , & extop , " extrudefaceregion " ) ;
2009-05-18 14:55:34 +00:00
BMO_HeaderFlag_To_Slot ( bm , & extop , " edgefacein " ,
2011-11-01 14:36:23 +00:00
hflag , BM_VERT | BM_EDGE | BM_FACE ) ;
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 ) {
2011-09-17 04:59:14 +00:00
if ( ( md - > type = = eModifierType_Mirror ) & & ( md - > mode & eModifierMode_Realtime ) ) {
2009-05-18 14:55:34 +00:00
MirrorModifierData * mmd = ( MirrorModifierData * ) md ;
if ( mmd - > flag & MOD_MIR_CLIPPING ) {
float mtx [ 4 ] [ 4 ] ;
if ( mmd - > mirror_ob ) {
float imtx [ 4 ] [ 4 ] ;
2009-11-23 14:41:22 +00:00
invert_m4_m4 ( imtx , mmd - > mirror_ob - > obmat ) ;
mul_m4_m4m4 ( mtx , obedit - > obmat , imtx ) ;
2009-05-18 14:55:34 +00:00
}
for ( edge = BMIter_New ( & iter , bm , BM_EDGES_OF_MESH , NULL ) ;
edge ; edge = BMIter_Step ( & iter ) )
{
2011-11-01 14:36:23 +00:00
if ( BM_TestHFlag ( edge , hflag ) ) {
2009-05-18 14:55:34 +00:00
float co1 [ 3 ] , co2 [ 3 ] ;
2009-11-23 14:41:22 +00:00
copy_v3_v3 ( co1 , edge - > v1 - > co ) ;
copy_v3_v3 ( co2 , edge - > v2 - > co ) ;
2009-05-18 14:55:34 +00:00
if ( mmd - > mirror_ob ) {
2009-11-23 14:41:22 +00:00
mul_v3_m4v3 ( co1 , mtx , co1 ) ;
mul_v3_m4v3 ( co2 , mtx , co2 ) ;
2009-05-18 14:55:34 +00:00
}
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 ) ;
}
}
}
}
}
2011-10-10 14:56:09 +00:00
EDBM_clear_flag_all ( em , BM_SELECT ) ;
2009-11-04 09:37:08 +00:00
2009-05-18 14:55:34 +00:00
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
2011-11-01 14:36:23 +00:00
if ( el - > htype = = BM_FACE ) {
2009-06-02 07:40:32 +00:00
f = ( BMFace * ) el ;
add_normal_aligned ( nor , f - > no ) ;
} ;
2009-05-18 14:55:34 +00:00
}
2009-11-23 14:41:22 +00:00
normalize_v3 ( nor ) ;
2009-06-02 07:40:32 +00:00
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
}
2011-11-01 14:36:23 +00:00
static short EDBM_Extrude_vert ( Object * obedit , BMEditMesh * em , const char hflag , float * nor )
2009-05-18 14:55:34 +00:00
{
2011-10-10 14:56:09 +00:00
BMIter iter ;
BMEdge * eed ;
2009-05-18 14:55:34 +00:00
2011-10-10 14:56:09 +00:00
/*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 ) ) {
2011-11-01 14:36:23 +00:00
if ( BM_TestHFlag ( eed , hflag ) ) {
if ( hflag & BM_SELECT ) {
2011-10-10 14:56:09 +00:00
BM_Select ( em - > bm , eed - > v1 , 1 ) ;
BM_Select ( em - > bm , eed - > v2 , 1 ) ;
}
2011-11-01 14:36:23 +00:00
BM_SetHFlag ( eed - > v1 , hflag & ~ BM_SELECT ) ;
BM_SetHFlag ( eed - > v2 , hflag & ~ BM_SELECT ) ;
2011-10-10 14:56:09 +00:00
} else {
2011-11-01 14:36:23 +00:00
if ( BM_TestHFlag ( eed - > v1 , hflag ) & & BM_TestHFlag ( eed - > v2 , hflag ) ) {
if ( hflag & BM_SELECT ) {
2011-10-10 14:56:09 +00:00
BM_Select ( em - > bm , eed , 1 ) ;
2009-05-19 00:33:54 +00:00
}
2011-09-30 04:27:12 +00:00
2011-11-01 14:36:23 +00:00
BM_SetHFlag ( eed , hflag & ~ BM_SELECT ) ;
2009-05-18 14:55:34 +00:00
}
}
2011-10-10 14:56:09 +00:00
}
2009-05-18 14:55:34 +00:00
2011-11-01 14:36:23 +00:00
return EDBM_Extrude_edge ( obedit , em , hflag , 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-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 ] ;
2009-11-23 14:41:22 +00:00
normalize_v3 ( dvec ) ;
2009-05-18 14:55:34 +00:00
dvec [ 0 ] * = offs ;
dvec [ 1 ] * = offs ;
dvec [ 2 ] * = offs ;
/* base correction */
2009-11-23 14:41:22 +00:00
copy_m3_m4 ( bmat , obedit - > obmat ) ;
invert_m3_m3 ( tmat , bmat ) ;
mul_m3_v3 ( tmat , dvec ) ;
2009-05-18 14:55:34 +00:00
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 ) ;
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 " ;
2011-09-23 13:31:48 +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 */
2011-05-11 02:14:43 +00:00
static int EDBM_Extrude_Mesh ( Scene * scene , Object * obedit , BMEditMesh * em , wmOperator * op , float * norin )
2009-05-18 14:55:34 +00:00
{
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 )
2011-10-10 14:56:09 +00:00
transmode = EDBM_Extrude_vert ( obedit , em , BM_SELECT , nor ) ;
else if ( nr = = 1 ) transmode = EDBM_Extrude_edge ( obedit , em , BM_SELECT , nor ) ;
else if ( nr = = 4 ) transmode = EDBM_Extrude_verts_indiv ( em , op , BM_SELECT , nor ) ;
else if ( nr = = 3 ) transmode = EDBM_Extrude_edges_indiv ( em , op , BM_SELECT , nor ) ;
else transmode = EDBM_Extrude_face_indiv ( em , op , BM_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 ' ) {
2009-11-23 14:41:22 +00:00
mul_m4_v3 ( obedit - > obmat , nor ) ;
sub_v3_v3v3 ( nor , nor , obedit - > obmat [ 3 ] ) ;
2009-05-18 14:55:34 +00:00
// 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 )
{
2010-07-22 04:45:18 +00:00
Scene * scene = CTX_data_scene ( 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
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
2010-07-22 04:45:18 +00:00
EDBM_Extrude_Mesh ( scene , obedit , em , op , NULL ) ;
2011-08-28 17:15:24 +00:00
/*This normally happens when pushing undo but modal operators
like this one don ' t push undo data until after modal mode is
done . */
EDBM_RecalcNormals ( em ) ;
BMEdit_RecalcTesselation ( em ) ;
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 ;
}
void MESH_OT_extrude_region ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Extrude Region " ;
ot - > idname = " MESH_OT_extrude_region " ;
/* api callbacks */
2010-07-22 00:18:35 +00:00
//ot->invoke= mesh_extrude_region_invoke;
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 - > exec = mesh_extrude_region_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
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 ;
}
void MESH_OT_extrude_verts_indiv ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Extrude Only Vertices " ;
ot - > idname = " MESH_OT_extrude_verts_indiv " ;
/* api callbacks */
ot - > exec = mesh_extrude_verts_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* to give to transform */
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
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 - > exec = mesh_extrude_edges_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* to give to transform */
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 ;
}
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 - > 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 ;
2009-07-16 06:27:37 +00:00
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
/* ******************** (de)select all operator **************** */
void EDBM_toggle_select_all ( BMEditMesh * em ) /* exported for UV */
{
if ( em - > bm - > totvertsel | | em - > bm - > totedgesel | | em - > bm - > totfacesel )
2011-10-10 14:56:09 +00:00
EDBM_clear_flag_all ( em , BM_SELECT ) ;
2009-05-28 04:41:02 +00:00
else
2011-10-10 14:56:09 +00:00
EDBM_set_flag_all ( em , BM_SELECT ) ;
2009-05-28 04:41:02 +00:00
}
2011-12-02 19:43:53 +00:00
static int mesh_select_all_exec ( bContext * C , wmOperator * op )
2009-05-28 04:41:02 +00:00
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
2011-12-02 19:43:53 +00:00
int action = RNA_enum_get ( op - > ptr , " action " ) ;
2009-05-28 04:41:02 +00:00
2011-12-02 19:43:53 +00:00
switch ( action ) {
case SEL_TOGGLE :
EDBM_toggle_select_all ( em ) ;
break ;
case SEL_SELECT :
EDBM_set_flag_all ( em , BM_SELECT ) ;
break ;
case SEL_DESELECT :
EDBM_clear_flag_all ( em , BM_SELECT ) ;
break ;
case SEL_INVERT :
EDBM_select_swap ( em ) ;
break ;
}
2009-05-28 04:41:02 +00:00
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 ;
}
2010-01-05 22:33:41 +00:00
void MESH_OT_select_all ( wmOperatorType * ot )
2009-05-28 04:41:02 +00:00
{
/* identifiers */
2009-07-16 06:27:37 +00:00
ot - > name = " Select/Deselect All " ;
2010-01-05 22:33:41 +00:00
ot - > idname = " MESH_OT_select_all " ;
2011-09-23 13:31:48 +00:00
ot - > description = " (de)select all vertices, edges or faces " ;
2009-05-28 04:41:02 +00:00
/* api callbacks */
2011-12-02 19:43:53 +00:00
ot - > exec = mesh_select_all_exec ;
2009-05-28 04:41:02 +00:00
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2011-12-01 14:12:43 +00:00
WM_operator_properties_select_all ( ot ) ;
2009-05-28 04:41:02 +00:00
}
2009-06-02 07:40:32 +00:00
/* *************** add-click-mesh (extrude) operator ************** */
2011-05-11 14:05:22 +00:00
/* in trunk see: 'editmesh_add.c' */
2009-06-02 07:40:32 +00:00
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 ;
2011-05-11 14:05:22 +00:00
short use_proj ;
2009-06-02 07:40:32 +00:00
em_setup_viewcontext ( C , & vc ) ;
2011-05-11 14:05:22 +00:00
use_proj = ( vc . scene - > toolsettings - > snap_flag & SCE_SNAP ) & & ( vc . scene - > toolsettings - > snap_mode = = SCE_SNAP_MODE_FACE ) ;
2009-06-02 07:40:32 +00:00
INIT_MINMAX ( min , max ) ;
2011-05-11 14:05:22 +00:00
BM_ITER ( v1 , & iter , vc . em - > bm , BM_VERTS_OF_MESH , NULL ) {
if ( BM_TestHFlag ( v1 , BM_SELECT ) ) {
DO_MINMAX ( v1 - > co , min , max ) ;
done = 1 ;
}
2009-06-02 07:40:32 +00:00
}
/* call extrude? */
if ( done ) {
2011-05-11 14:05:22 +00:00
const short rot_src = RNA_boolean_get ( op - > ptr , " rotate_source " ) ;
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 } ;
2011-05-11 14:05:22 +00:00
/* 2D normal calc */
float mval_f [ 2 ] ;
mval_f [ 0 ] = ( float ) event - > mval [ 0 ] ;
mval_f [ 1 ] = ( float ) event - > mval [ 1 ] ;
2009-06-02 07:40:32 +00:00
/* 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 ) {
2011-05-11 14:05:22 +00:00
if ( BM_TestHFlag ( eed , BM_SELECT ) ) {
float co1 [ 3 ] , co2 [ 3 ] ;
mul_v3_m4v3 ( co1 , vc . obedit - > obmat , eed - > v1 - > co ) ;
mul_v3_m4v3 ( co2 , vc . obedit - > obmat , eed - > v2 - > co ) ;
project_float_noclip ( vc . ar , co1 , co1 ) ;
project_float_noclip ( vc . ar , co2 , co2 ) ;
/* 2D rotate by 90d while adding.
* ( x , y ) = ( y , - x )
*
* accumulate the screenspace normal in 2 D ,
* with screenspace edge length weighting the result . */
if ( line_point_side_v2 ( co1 , co2 , mval_f ) > = 0.0f ) {
nor [ 0 ] + = ( co1 [ 1 ] - co2 [ 1 ] ) ;
nor [ 1 ] + = - ( co1 [ 0 ] - co2 [ 0 ] ) ;
}
else {
nor [ 0 ] + = ( co2 [ 1 ] - co1 [ 1 ] ) ;
nor [ 1 ] + = - ( co2 [ 0 ] - co1 [ 0 ] ) ;
}
2009-06-02 07:40:32 +00:00
}
2011-05-11 14:05:22 +00:00
done = 1 ;
}
if ( done ) {
float view_vec [ 3 ] , cross [ 3 ] ;
/* convert the 2D nomal into 3D */
mul_mat3_m4_v3 ( vc . rv3d - > viewinv , nor ) ; /* worldspace */
mul_mat3_m4_v3 ( vc . obedit - > imat , nor ) ; /* local space */
/* correct the normal to be aligned on the view plane */
copy_v3_v3 ( view_vec , vc . rv3d - > viewinv [ 2 ] ) ;
mul_mat3_m4_v3 ( vc . obedit - > imat , view_vec ) ;
cross_v3_v3v3 ( cross , nor , view_vec ) ;
cross_v3_v3v3 ( nor , view_vec , cross ) ;
normalize_v3 ( nor ) ;
2009-06-02 07:40:32 +00:00
}
/* center */
2011-05-11 14:05:22 +00:00
mid_v3_v3v3 ( cent , min , max ) ;
copy_v3_v3 ( min , cent ) ;
2009-11-23 14:41:22 +00:00
mul_m4_v3 ( vc . obedit - > obmat , min ) ; // view space
2011-05-11 14:05:22 +00:00
view3d_get_view_aligned_coordinate ( & vc , min , event - > mval , TRUE ) ;
2009-11-23 14:41:22 +00:00
mul_m4_v3 ( vc . obedit - > imat , min ) ; // back in object space
2011-05-11 14:05:22 +00:00
sub_v3_v3 ( min , cent ) ;
2009-06-02 07:40:32 +00:00
/* calculate rotation */
2009-11-23 14:41:22 +00:00
unit_m3 ( mat ) ;
2009-06-02 07:40:32 +00:00
if ( done ) {
float dot ;
2011-05-11 14:05:22 +00:00
copy_v3_v3 ( vec , min ) ;
2009-11-23 14:41:22 +00:00
normalize_v3 ( vec ) ;
2011-11-16 17:37:20 +00:00
dot = dot_v3v3 ( vec , nor ) ;
2009-06-02 07:40:32 +00:00
if ( fabs ( dot ) < 0.999 ) {
float cross [ 3 ] , si , q1 [ 4 ] ;
2011-05-11 14:05:22 +00:00
2009-11-23 14:41:22 +00:00
cross_v3_v3v3 ( cross , nor , vec ) ;
normalize_v3 ( cross ) ;
2009-06-02 07:40:32 +00:00
dot = 0.5f * saacos ( dot ) ;
2011-05-11 14:05:22 +00:00
/* halve the rotation if its applied twice */
if ( rot_src ) dot * = 0.5f ;
2009-06-02 07:40:32 +00:00
si = ( float ) sin ( dot ) ;
q1 [ 0 ] = ( float ) cos ( dot ) ;
q1 [ 1 ] = cross [ 0 ] * si ;
q1 [ 2 ] = cross [ 1 ] * si ;
q1 [ 3 ] = cross [ 2 ] * si ;
2009-11-23 14:41:22 +00:00
quat_to_mat3 ( mat , q1 ) ;
2009-06-02 07:40:32 +00:00
}
}
2011-05-11 14:05:22 +00:00
if ( rot_src ) {
EDBM_CallOpf ( vc . em , op , " rotate verts=%hv cent=%v mat=%m3 " ,
BM_SELECT , cent , mat ) ;
/* also project the source, for retopo workflow */
if ( use_proj )
EMBM_project_snap_verts ( C , vc . ar , vc . obedit , vc . em ) ;
}
2009-06-18 02:05:56 +00:00
2011-10-10 14:56:09 +00:00
EDBM_Extrude_edge ( vc . obedit , vc . em , BM_SELECT , nor ) ;
2009-06-18 02:05:56 +00:00
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
2011-05-11 14:05:22 +00:00
copy_v3_v3 ( min , curs ) ;
2011-05-08 23:43:18 +00:00
view3d_get_view_aligned_coordinate ( & vc , min , event - > mval , 0 ) ;
2011-05-11 14:05:22 +00:00
2009-11-23 14:41:22 +00:00
invert_m4_m4 ( vc . obedit - > imat , vc . obedit - > obmat ) ;
mul_m4_v3 ( 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
2011-05-11 14:05:22 +00:00
if ( use_proj )
EMBM_project_snap_verts ( C , vc . ar , vc . obedit , vc . em ) ;
2011-11-01 23:38:34 +00:00
/*This normally happens when pushing undo but modal operators
like this one don ' t push undo data until after modal mode is
done . */
EDBM_RecalcNormals ( vc . em ) ;
BMEdit_RecalcTesselation ( vc . em ) ;
2009-09-16 17:43:09 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , vc . obedit - > data ) ;
2011-02-27 06:19:40 +00:00
DAG_id_tag_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 ;
2011-09-23 13:31:48 +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 ;
2011-05-11 14:05:22 +00:00
RNA_def_boolean ( ot - > srna , " rotate_source " , 1 , " Rotate Source " , " Rotate initial selection giving better shape " ) ;
2009-06-02 07:40:32 +00:00
}
2009-06-18 01:31:50 +00:00
2011-02-27 06:19:40 +00:00
static int delete_mesh ( bContext * C , Object * obedit , wmOperator * op , int event , Scene * UNUSED ( 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 ;
}
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 " , " " } ,
2011-04-24 07:49:21 +00:00
{ 12 , " COLLAPSE " , 0 , " Collapse " , " " } ,
2009-07-16 06:27:37 +00:00
{ 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 ) ;
2011-04-24 07:49:21 +00:00
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
2009-06-18 01:31:50 +00:00
Scene * scene = CTX_data_scene ( C ) ;
2011-04-24 07:49:21 +00:00
int type = RNA_enum_get ( op - > ptr , " type " ) ;
if ( type ! = 12 ) {
2011-08-28 17:15:24 +00:00
if ( delete_mesh ( C , obedit , op , type , scene ) = = OPERATOR_CANCELLED )
return OPERATOR_CANCELLED ;
EDBM_clear_flag_all ( em , BM_SELECT ) ;
2011-04-24 07:49:21 +00:00
} else {
if ( ! EDBM_CallOpf ( em , op , " collapse edges=%he " , BM_SELECT ) )
return OPERATOR_CANCELLED ;
2011-08-26 11:28:42 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2011-04-24 07:49:21 +00:00
}
2011-08-28 17:15:24 +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 " ;
2011-09-23 13:31:48 +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 */
2010-03-10 11:16:26 +00:00
ot - > prop = RNA_def_enum ( ot - > srna , " type " , prop_mesh_delete_types , 10 , " Type " , " Method used for deleting mesh data " ) ;
2009-06-18 01:31:50 +00:00
}
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 ) ;
2011-02-27 06:19:40 +00:00
DAG_id_tag_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 " ;
2011-09-23 13:31:48 +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 ;
}
2011-05-11 02:14:43 +00:00
static void MESH_OT_selection_type ( wmOperatorType * ot )
2009-06-18 10:15:23 +00:00
{
/* identifiers */
ot - > name = " Selection Mode " ;
2011-09-23 13:31:48 +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 )
{
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 ) {
2011-05-12 01:55:08 +00:00
BM_ITER ( eed , & iter , bm , BM_EDGES_OF_MESH , NULL ) {
if ( ! BM_TestHFlag ( eed , BM_SELECT ) | | BM_TestHFlag ( eed , BM_HIDDEN ) )
continue ;
2009-08-05 06:06:58 +00:00
BM_ClearHFlag ( eed , BM_SEAM ) ;
2009-07-16 06:27:37 +00:00
}
}
else {
2011-05-12 01:55:08 +00:00
BM_ITER ( eed , & iter , bm , BM_EDGES_OF_MESH , NULL ) {
if ( ! BM_TestHFlag ( eed , BM_SELECT ) | | BM_TestHFlag ( eed , BM_HIDDEN ) )
continue ;
2009-08-05 06:06:58 +00:00
BM_SetHFlag ( eed , BM_SEAM ) ;
2009-07-16 06:27:37 +00:00
}
}
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 " ;
2011-09-23 13:31:48 +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 )
{
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 ) {
2011-05-12 01:55:08 +00:00
BM_ITER ( eed , & iter , bm , BM_EDGES_OF_MESH , NULL ) {
if ( ! BM_TestHFlag ( eed , BM_SELECT ) | | BM_TestHFlag ( eed , BM_HIDDEN ) )
continue ;
2009-08-05 06:06:58 +00:00
BM_SetHFlag ( eed , BM_SHARP ) ;
2009-07-16 06:27:37 +00:00
}
} else {
2011-05-12 01:55:08 +00:00
BM_ITER ( eed , & iter , bm , BM_EDGES_OF_MESH , NULL ) {
if ( ! BM_TestHFlag ( eed , BM_SELECT ) | | BM_TestHFlag ( eed , BM_HIDDEN ) )
continue ;
2009-08-05 06:06:58 +00:00
BM_ClearHFlag ( eed , BM_SHARP ) ;
2009-07-16 06:27:37 +00:00
}
}
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 " ;
2011-09-23 13:31:48 +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
2011-10-10 14:56:09 +00:00
static int editbmesh_vert_connect ( bContext * C , wmOperator * op )
2009-07-17 05:09:33 +00:00
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
BMesh * bm = em - > bm ;
BMOperator bmop ;
int len = 0 ;
2011-10-10 14:56:09 +00:00
if ( ! EDBM_InitOpf ( em , & bmop , op , " connectverts verts=%hv " , BM_SELECT ) ) {
return OPERATOR_CANCELLED ;
}
2009-07-17 05:09:33 +00:00
BMO_Exec_Op ( bm , & bmop ) ;
len = BMO_GetSlot ( & bmop , " edgeout " ) - > len ;
2011-10-10 14:56:09 +00:00
if ( ! EDBM_FinishOp ( em , & bmop , op , 1 ) ) {
return OPERATOR_CANCELLED ;
}
2009-07-17 05:09:33 +00:00
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 )
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
BMesh * bm = em - > bm ;
BMOperator bmop ;
int len = 0 ;
2011-10-10 14:56:09 +00:00
if ( ! EDBM_InitOpf ( em , & bmop , op , " edgesplit edges=%he numcuts=%d " ,
BM_SELECT , RNA_int_get ( op - > ptr , " number_cuts " ) ) ) {
return OPERATOR_CANCELLED ;
}
2009-07-17 06:05:09 +00:00
BMO_Exec_Op ( bm , & bmop ) ;
len = BMO_GetSlot ( & bmop , " outsplit " ) - > len ;
2011-10-10 14:56:09 +00:00
if ( ! EDBM_FinishOp ( em , & bmop , op , 1 ) ) {
return OPERATOR_CANCELLED ;
}
2009-07-17 06:05:09 +00:00
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 )
{
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 ;
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( ob - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , ob - > data ) ;
2009-07-21 08:39:58 +00:00
return OPERATOR_FINISHED ;
}
2011-04-13 22:30:25 +00:00
static int mesh_duplicate_invoke ( bContext * C , wmOperator * op , wmEvent * UNUSED ( event ) )
2009-07-21 08:39:58 +00:00
{
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 " ;
2011-09-23 13:31:48 +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 )
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( ( Mesh * ) obedit - > data ) ) - > edit_btmesh ;
2010-09-25 01:54:58 +00:00
if ( ! EDBM_CallOpf ( em , op , " reversefaces faces=%hf " , BM_SELECT ) )
2009-07-22 02:57:40 +00:00
return OPERATOR_CANCELLED ;
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 ;
}
2010-07-14 22:06:10 +00:00
float * bm_get_cd_float ( CustomData * cdata , void * data , int type )
{
float * f = CustomData_bmesh_get ( cdata , data , type ) ;
return f ;
}
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 )
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
BMOperator bmop ;
BMEdge * eed ;
BMIter iter ;
2011-09-09 04:09:34 +00:00
const int do_ccw = RNA_enum_get ( op - > ptr , " direction " ) = = 1 ;
int do_deselect = FALSE ; /* do we deselect */
2009-07-26 14:58:31 +00:00
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 ) {
2011-09-12 15:10:59 +00:00
if ( ( BM_TestHFlag ( eed - > l - > f , BM_SELECT ) & & BM_TestHFlag ( eed - > l - > radial_next - > f , BM_SELECT ) )
& & ! ( BM_TestHFlag ( eed - > l - > f , BM_HIDDEN ) | | BM_TestHFlag ( eed - > l - > radial_next - > f , BM_HIDDEN ) ) )
2009-08-05 06:06:58 +00:00
{
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 ) {
2011-05-12 01:55:08 +00:00
BM_ITER ( eed , & iter , em - > bm , BM_EDGES_OF_MESH , NULL ) {
2011-09-09 04:09:34 +00:00
if ( BM_TestHFlag ( eed , BM_SELECT ) & & ! BM_TestHFlag ( eed , BM_HIDDEN ) ) {
/* de-select the edge before */
do_deselect = TRUE ;
2009-07-26 14:58:31 +00:00
break ;
2011-09-09 04:09:34 +00:00
}
2009-07-26 14:58:31 +00:00
}
}
/*this should never happen*/
if ( ! eed )
return OPERATOR_CANCELLED ;
2011-09-09 04:09:34 +00:00
EDBM_InitOpf ( em , & bmop , op , " edgerotate edges=%e ccw=%d " , eed , do_ccw ) ;
2009-07-26 14:58:31 +00:00
2011-09-09 04:09:34 +00:00
/* avoid adding to the selection if we start off with only a selected edge,
* we could also just deselect the single edge easily but use the BMO api
* since it seems this is more ' correct ' */
if ( do_deselect ) BMO_UnHeaderFlag_Buffer ( em - > bm , & bmop , " edges " , BM_SELECT , BM_EDGE ) ;
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 ;
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 " ;
2011-09-23 13:31:48 +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 */
2011-09-23 13:31:48 +00:00
RNA_def_enum ( ot - > srna , " direction " , direction_items , DIRECTION_CW , " direction " , " direction to rotate edge around " ) ;
2009-07-26 14:58:31 +00:00
}
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 ) ;
}
2011-08-28 17:15:24 +00:00
EDBM_selectmode_flush ( em ) ;
2009-08-05 06:06:58 +00:00
/*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 ) ;
BMEditMesh * em = ( ( ( Mesh * ) obedit - > data ) ) - > edit_btmesh ;
EDBM_hide_mesh ( em , RNA_boolean_get ( op - > ptr , " unselected " ) ) ;
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 ;
2011-09-23 13:31:48 +00:00
ot - > description = " Hide (un)selected vertices, edges or faces " ;
2009-08-26 10:27:04 +00:00
2009-08-05 06:06:58 +00:00
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* props */
2011-09-23 13:31:48 +00:00
RNA_def_boolean ( ot - > srna , " unselected " , 0 , " Unselected " , " Hide unselected rather than selected " ) ;
2009-08-05 06:06:58 +00:00
}
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 } ;
2011-09-30 04:27:12 +00:00
int sels [ 3 ] = {
( em - > selectmode & SCE_SELECT_VERTEX ) ,
( em - > selectmode & SCE_SELECT_EDGE ) ,
( em - > selectmode & SCE_SELECT_FACE ) ,
} ;
/* Use index field to remember what was hidden before all is revealed. */
for ( i = 0 ; i < 3 ; i + + ) {
2009-08-05 06:06:58 +00:00
BM_ITER ( ele , & iter , em - > bm , types [ i ] , NULL ) {
2011-11-01 12:51:38 +00:00
if ( BM_TestHFlag ( ele , BM_HIDDEN ) ) {
BM_SetHFlag ( ele , BM_TMP_TAG ) ;
}
else {
BM_ClearHFlag ( ele , BM_TMP_TAG ) ;
}
2011-09-30 04:27:12 +00:00
}
}
2009-08-05 06:06:58 +00:00
2011-09-30 04:27:12 +00:00
/* Reveal everything */
EDBM_clear_flag_all ( em , BM_HIDDEN ) ;
/* Select relevant just-revealed elements */
for ( i = 0 ; i < 3 ; i + + ) {
if ( ! sels [ i ] ) {
continue ;
}
BM_ITER ( ele , & iter , em - > bm , types [ i ] , NULL ) {
2011-11-01 12:51:38 +00:00
if ( BM_TestHFlag ( ele , BM_TMP_TAG ) ) {
2011-09-30 04:27:12 +00:00
BM_Select ( em - > bm , ele , 1 ) ;
2009-08-05 06:06:58 +00:00
}
}
}
EDBM_selectmode_flush ( em ) ;
}
2011-03-28 00:29:45 +00:00
static int reveal_mesh_exec ( bContext * C , wmOperator * UNUSED ( op ) )
2009-08-05 06:06:58 +00:00
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( ( Mesh * ) obedit - > data ) ) - > edit_btmesh ;
EDBM_reveal_mesh ( em ) ;
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 " ;
2011-09-23 13:31:48 +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 )
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
2011-09-06 04:06:05 +00:00
/* doflip has to do with bmesh_rationalize_normals, it's an internal
* thing */
2011-03-30 22:46:56 +00:00
if ( ! EDBM_CallOpf ( em , op , " righthandfaces faces=%hf doflip=%d " , BM_SELECT , 1 ) )
2009-08-06 08:23:10 +00:00
return OPERATOR_CANCELLED ;
2011-09-06 04:06:05 +00:00
2009-08-06 08:23:10 +00:00
if ( RNA_boolean_get ( op - > ptr , " inside " ) )
2011-09-06 04:06:05 +00:00
EDBM_CallOpf ( em , op , " reversefaces faces=%hf " , BM_SELECT ) ;
2009-08-06 08:23:10 +00:00
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 )
{
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 ;
2011-10-26 07:41:56 +00:00
/* mirror before smooth */
if ( ( ( Mesh * ) obedit - > data ) - > editflag & ME_EDIT_MIRROR_X ) {
2011-11-01 05:43:35 +00:00
EDBM_CacheMirrorVerts ( em , TRUE ) ;
2011-10-26 07:41:56 +00:00
}
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
/* 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 ) {
2011-09-17 04:59:14 +00:00
if ( md - > type = = eModifierType_Mirror & & ( md - > mode & eModifierMode_Realtime ) ) {
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
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 ;
}
}
2011-10-26 07:41:56 +00:00
/* apply mirror */
if ( ( ( Mesh * ) obedit - > data ) - > editflag & ME_EDIT_MIRROR_X ) {
EDBM_ApplyMirrorCache ( em , BM_SELECT , 0 ) ;
EDBM_EndMirrorCache ( em ) ;
}
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
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 " ;
2011-09-23 13:31:48 +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
2011-03-28 00:29:45 +00:00
static int bm_test_exec ( bContext * C , wmOperator * UNUSED ( op ) )
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
{
Object * obedit = CTX_data_edit_object ( C ) ;
2011-04-24 07:45:24 +00:00
ARegion * ar = CTX_wm_region ( C ) ;
View3D * v3d = CTX_wm_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 ;
2011-08-30 01:59:33 +00:00
BMBVHTree * tree = BMBVH_NewBVH ( em , 0 , NULL , NULL ) ;
2009-10-07 21:19:58 +00:00
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 ;
2011-04-24 07:45:24 +00:00
if ( ! BMBVH_EdgeVisible ( tree , e , ar , v3d , obedit ) )
2009-10-07 21:19:58 +00:00
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 ) ;
}
}
2011-11-24 00:14:13 +00:00
BMW_Init ( & walker , em - > bm , BMW_UVISLAND , BMW_NIL_LAY ) ;
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
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
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 *************************/
2011-05-11 02:14:43 +00:00
static void mesh_set_smooth_faces ( BMEditMesh * em , short smooth )
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
{
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 ) ;
}
}
}
2011-04-13 22:30:25 +00:00
static int mesh_faces_shade_smooth_exec ( bContext * C , wmOperator * UNUSED ( op ) )
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
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
mesh_set_smooth_faces ( em , 1 ) ;
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 " ;
2011-09-23 13:31:48 +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 ;
}
2011-04-13 22:30:25 +00:00
static int mesh_faces_shade_flat_exec ( bContext * C , wmOperator * UNUSED ( op ) )
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
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
mesh_set_smooth_faces ( em , 0 ) ;
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 " ;
2011-09-23 13:31:48 +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
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 */
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( ob - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , ob - > data ) ;
2011-11-20 16:21:13 +00:00
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
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 */
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( ob - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , ob - > data ) ;
2011-11-20 16:21:13 +00:00
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
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 */
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( ob - > data , OB_RECALC_DATA ) ;
2009-09-20 18:18:40 +00:00
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
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 ;
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( ob - > data , OB_RECALC_DATA ) ;
2009-09-20 18:18:40 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , ob - > data ) ;
/* we succeeded */
return OPERATOR_FINISHED ;
2009-08-28 10:17:31 +00:00
}
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 */
2011-09-23 13:31:48 +00:00
RNA_def_enum ( ot - > srna , " direction " , direction_items , DIRECTION_CW , " Direction " , " Direction to rotate UVs around " ) ;
2009-08-28 10:17:31 +00:00
}
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 */
2011-09-23 13:31:48 +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 */
2011-12-02 16:57:22 +00:00
RNA_def_enum ( ot - > srna , " direction " , direction_items , DIRECTION_CCW , " Direction " , " Direction to rotate edge around " ) ;
2009-08-28 10:17:31 +00:00
}
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 */
2011-09-23 13:31:48 +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 ;
2011-09-07 06:49:20 +00:00
float * vco = NULL , co [ 3 ] , cent [ 3 ] = { 0.0f , 0.0f , 0.0f } ;
2009-08-31 23:07:05 +00:00
if ( target ) {
2009-09-12 04:03:26 +00:00
vco = give_cursor ( scene , v3d ) ;
2011-09-12 05:51:35 +00:00
copy_v3_v3 ( co , vco ) ;
2009-11-23 14:41:22 +00:00
mul_m4_v3 ( ob - > imat , co ) ;
2011-09-07 06:49:20 +00:00
}
else {
float fac ;
int i = 0 ;
2009-08-31 23:07:05 +00:00
BM_ITER ( v , & iter , em - > bm , BM_VERTS_OF_MESH , NULL ) {
if ( ! BM_TestHFlag ( v , BM_SELECT ) )
continue ;
2011-11-07 09:02:10 +00:00
add_v3_v3 ( cent , v - > co ) ;
2009-08-31 23:07:05 +00:00
i + + ;
}
if ( ! i )
return OPERATOR_CANCELLED ;
fac = 1.0f / ( float ) i ;
2011-02-27 06:19:40 +00:00
mul_v3_fl ( cent , fac ) ;
copy_v3_v3 ( co , cent ) ;
2010-07-19 04:44:37 +00:00
vco = co ;
2009-08-31 23:07:05 +00:00
}
2010-07-19 04:44:37 +00:00
if ( ! vco )
2009-08-31 23:07:05 +00:00
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 ;
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 } } ;
2011-05-31 05:11:04 +00:00
static EnumPropertyItem * merge_type_itemf ( bContext * C , PointerRNA * UNUSED ( ptr ) , PropertyRNA * UNUSED ( prop ) , int * free )
2009-08-31 23:07:05 +00:00
{
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 & &
2011-11-01 14:36:23 +00:00
( ( BMEditSelection * ) em - > bm - > selected . first ) - > htype = = BM_VERT & & ( ( BMEditSelection * ) em - > bm - > selected . last ) - > htype = = BM_VERT ) {
2009-08-31 23:07:05 +00:00
RNA_enum_items_add_value ( & item , & totitem , merge_type_items , 6 ) ;
RNA_enum_items_add_value ( & item , & totitem , merge_type_items , 1 ) ;
}
2011-11-01 14:36:23 +00:00
else if ( em - > bm - > selected . first & & ( ( BMEditSelection * ) em - > bm - > selected . first ) - > htype = = BM_VERT )
2009-08-31 23:07:05 +00:00
RNA_enum_items_add_value ( & item , & totitem , merge_type_items , 1 ) ;
2011-11-01 14:36:23 +00:00
else if ( em - > bm - > selected . last & & ( ( BMEditSelection * ) em - > bm - > selected . last ) - > htype = = BM_VERT )
2009-08-31 23:07:05 +00:00
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 )
{
/* 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 */
2011-09-23 13:31:48 +00:00
ot - > prop = RNA_def_enum ( ot - > srna , " type " , merge_type_items , 3 , " Type " , " Merge method to use " ) ;
2010-07-22 04:45:18 +00:00
RNA_def_enum_funcs ( ot - > prop , merge_type_itemf ) ;
2011-09-23 13:31:48 +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 ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
BMOperator bmop ;
2011-09-07 06:49:20 +00:00
/* int count; */ /* UNUSED */
2009-09-09 06:28:58 +00:00
EDBM_InitOpf ( em , & bmop , op , " finddoubles verts=%hv dist=%f " ,
BM_SELECT , RNA_float_get ( op - > ptr , " mergedist " ) ) ;
BMO_Exec_Op ( em - > bm , & bmop ) ;
2011-09-07 06:49:20 +00:00
/* count = BMO_CountSlotMap(em->bm, &bmop, "targetmapout"); */ /* UNUSED */
2009-09-09 06:28:58 +00:00
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 ) ;
}
*/
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-09-16 17:43:09 +00:00
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 " ,
2011-09-23 13:31:48 +00:00
" Minimum distance between elements to merge " , 0.00001 , 10.0 ) ;
2009-09-09 06:28:58 +00:00
}
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 ;
2011-05-11 02:14:43 +00:00
static int select_vertex_path_exec ( bContext * C , wmOperator * op )
2009-09-20 18:18:40 +00:00
{
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 ;
2011-11-01 14:36:23 +00:00
if ( ( sv - > htype ! = BM_VERT ) | | ( ev - > htype ! = BM_VERT ) )
2009-09-20 18:18:40 +00:00
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 ) ;
*/
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( ob - > data , OB_RECALC_DATA ) ;
2009-09-20 18:18:40 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , ob - > data ) ;
/* we succeeded */
return OPERATOR_FINISHED ;
}
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 - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* properties */
2011-09-23 13:31:48 +00:00
RNA_def_enum ( ot - > srna , " type " , type_items , VPATH_SELECT_EDGE_LENGTH , " Type " , " Method to compute distance " ) ;
2009-09-20 18:18:40 +00:00
}
2009-10-07 21:19:58 +00:00
/********************** Rip Operator *************************/
/* helper to find edge for edge_rip */
2011-05-13 04:04:53 +00:00
static float mesh_rip_edgedist ( ARegion * ar , float mat [ ] [ 4 ] , float * co1 , float * co2 , const int mval [ 2 ] )
2009-10-07 21:19:58 +00:00
{
float vec1 [ 3 ] , vec2 [ 3 ] , mvalf [ 2 ] ;
2011-05-24 04:35:21 +00:00
ED_view3d_project_float ( ar , co1 , vec1 , mat ) ;
ED_view3d_project_float ( ar , co2 , vec2 , mat ) ;
2009-10-07 21:19:58 +00:00
mvalf [ 0 ] = ( float ) mval [ 0 ] ;
mvalf [ 1 ] = ( float ) mval [ 1 ] ;
2009-11-23 14:41:22 +00:00
return dist_to_line_segment_v2 ( mvalf , vec1 , vec2 ) ;
2009-10-07 21:19:58 +00:00
}
/* 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 ) ;
2011-04-24 07:45:24 +00:00
View3D * v3d = CTX_wm_view3d ( C ) ;
2009-10-07 21:19:58 +00:00
RegionView3D * rv3d = CTX_wm_region_view3d ( C ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
2011-10-12 06:11:21 +00:00
BMesh * bm = em - > bm ;
2009-10-07 21:19:58 +00:00
BMOperator bmop ;
BMBVHTree * bvhtree ;
BMOIter siter ;
BMIter iter , eiter , liter ;
BMLoop * l ;
BMEdge * e , * e2 , * closest = NULL ;
2011-10-12 06:11:21 +00:00
BMVert * v , * ripvert = NULL ;
2009-11-04 09:37:08 +00:00
int side = 0 , i , singlesel = 0 ;
2011-09-12 05:24:45 +00:00
float projectMat [ 4 ] [ 4 ] , fmval [ 3 ] = { event - > mval [ 0 ] , event - > mval [ 1 ] } ;
2009-10-07 21:19:58 +00:00
float dist = FLT_MAX , d ;
2011-05-24 04:35:21 +00:00
ED_view3d_ob_project_mat_get ( rv3d , obedit , projectMat ) ;
2009-10-07 21:19:58 +00:00
BM_ITER ( e , & iter , em - > bm , BM_EDGES_OF_MESH , NULL ) {
2011-11-01 12:51:38 +00:00
if ( BM_TestHFlag ( e , BM_SELECT ) ) {
BM_SetHFlag ( e , BM_TMP_TAG ) ;
}
else {
BM_ClearHFlag ( e , BM_TMP_TAG ) ;
}
2009-10-07 21:19:58 +00:00
}
2011-06-05 00:54:14 +00:00
/*handle case of one vert selected. identify
closest edge around that vert to mouse cursor ,
then rip two adjacent edges in the vert fan . */
2011-10-12 06:11:21 +00:00
if ( bm - > totvertsel = = 1 & & bm - > totedgesel = = 0 & & bm - > totfacesel = = 0 ) {
2009-11-04 09:37:08 +00:00
singlesel = 1 ;
2009-10-22 23:22:05 +00:00
/*find selected vert*/
2011-10-12 06:11:21 +00:00
BM_ITER ( v , & iter , 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 ;
2011-10-12 06:11:21 +00:00
if ( ! v - > e | | ! v - > e - > l ) {
BKE_report ( op - > reports , RPT_ERROR , " Selected vertex has no faces " ) ;
return OPERATOR_CANCELLED ;
}
2009-10-22 23:22:05 +00:00
/*find closest edge to mouse cursor*/
2009-10-07 21:19:58 +00:00
e2 = NULL ;
2011-10-12 06:11:21 +00:00
BM_ITER ( e , & iter , bm , BM_EDGES_OF_VERT , v ) {
2009-10-22 23:22:05 +00:00
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*/
2011-10-12 06:11:21 +00:00
if ( BM_Edge_FaceCount ( e2 ) = = 1 | | BM_Vert_FaceCount ( v ) = = 2 ) {
2010-07-14 22:06:10 +00:00
l = e2 - > l ;
2011-10-12 06:11:21 +00:00
ripvert = BM_Rip_Vertex ( bm , l - > f , v ) ;
2009-10-22 23:22:05 +00:00
2011-10-12 06:11:21 +00:00
BLI_assert ( ripvert ) ;
if ( ! ripvert ) {
return OPERATOR_CANCELLED ;
}
2009-10-22 23:22:05 +00:00
} else if ( BM_Edge_FaceCount ( e2 ) = = 2 ) {
2010-07-14 22:06:10 +00:00
l = e2 - > l ;
2009-11-04 09:37:08 +00:00
e = BM_OtherFaceLoop ( e2 , l - > f , v ) - > e ;
2011-11-01 12:51:38 +00:00
BM_SetHFlag ( e , BM_TMP_TAG ) ;
2011-10-12 06:11:21 +00:00
BM_Select ( bm , e , 1 ) ;
2009-10-22 23:22:05 +00:00
2010-07-14 22:06:10 +00:00
l = e2 - > l - > radial_next ;
2009-11-04 09:37:08 +00:00
e = BM_OtherFaceLoop ( e2 , l - > f , v ) - > e ;
2011-11-01 12:51:38 +00:00
BM_SetHFlag ( e , BM_TMP_TAG ) ;
2011-10-12 06:11:21 +00:00
BM_Select ( bm , e , 1 ) ;
2009-10-22 23:22:05 +00:00
}
2009-11-04 09:37:08 +00:00
dist = FLT_MAX ;
2009-10-22 23:22:05 +00:00
} else {
/*expand edge selection*/
2011-10-12 06:11:21 +00:00
BM_ITER ( v , & iter , bm , BM_VERTS_OF_MESH , NULL ) {
2009-10-22 23:22:05 +00:00
e2 = NULL ;
i = 0 ;
2011-10-12 06:11:21 +00:00
BM_ITER ( e , & eiter , bm , BM_EDGES_OF_VERT , v ) {
2011-11-01 12:51:38 +00:00
if ( BM_TestHFlag ( e , BM_TMP_TAG ) ) {
2009-10-22 23:22:05 +00:00
e2 = e ;
i + + ;
}
}
2010-07-14 22:06:10 +00:00
if ( i = = 1 & & e2 - > l ) {
l = BM_OtherFaceLoop ( e2 , e2 - > l - > f , v ) ;
2011-09-12 15:10:59 +00:00
l = l - > radial_next ;
2009-10-22 23:22:05 +00:00
l = BM_OtherFaceLoop ( l - > e , l - > f , v ) ;
if ( l )
2011-10-12 06:11:21 +00:00
BM_Select ( bm , l - > e , 1 ) ;
2009-10-22 23:22:05 +00:00
}
2009-10-07 21:19:58 +00:00
}
}
if ( ! EDBM_InitOpf ( em , & bmop , op , " edgesplit edges=%he " , BM_SELECT ) ) {
return OPERATOR_CANCELLED ;
}
2011-10-12 06:11:21 +00:00
BMO_Exec_Op ( bm , & bmop ) ;
2009-10-07 21:19:58 +00:00
/*build bvh tree for edge visibility tests*/
2011-08-30 01:59:33 +00:00
bvhtree = BMBVH_NewBVH ( em , 0 , NULL , NULL ) ;
2009-10-07 21:19:58 +00:00
for ( i = 0 ; i < 2 ; i + + ) {
2011-10-12 06:11:21 +00:00
BMO_ITER ( e , & siter , bm , & bmop , i ? " edgeout2 " : " edgeout1 " , BM_EDGE ) {
2011-09-12 05:24:45 +00:00
float cent [ 3 ] = { 0 , 0 , 0 } , mid [ 3 ] , vec [ 3 ] ;
2009-10-07 21:19:58 +00:00
2011-04-24 07:45:24 +00:00
if ( ! BMBVH_EdgeVisible ( bvhtree , e , ar , v3d , obedit ) | | ! e - > l )
2009-10-07 21:19:58 +00:00
continue ;
2011-09-12 05:24:45 +00:00
/* 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 . */
2011-10-12 06:11:21 +00:00
BM_ITER ( l , & liter , bm , BM_LOOPS_OF_FACE , e - > l - > f ) {
2011-09-12 05:24:45 +00:00
add_v3_v3 ( cent , l - > v - > co ) ;
2009-10-07 21:19:58 +00:00
}
2010-07-14 22:06:10 +00:00
mul_v3_fl ( cent , 1.0f / ( float ) e - > l - > f - > len ) ;
2009-10-07 21:19:58 +00:00
2011-09-12 05:24:45 +00:00
mid_v3_v3v3 ( mid , e - > v1 - > co , e - > v2 - > co ) ;
2009-11-23 14:41:22 +00:00
sub_v3_v3v3 ( vec , cent , mid ) ;
normalize_v3 ( vec ) ;
mul_v3_fl ( vec , 0.01f ) ;
add_v3_v3v3 ( mid , mid , vec ) ;
2009-10-07 21:19:58 +00:00
2011-09-12 05:24:45 +00:00
/* yay we have our comparison point, now project it */
2011-05-24 04:35:21 +00:00
ED_view3d_project_float ( ar , mid , mid , projectMat ) ;
2009-10-07 21:19:58 +00:00
2011-09-12 05:24:45 +00:00
d = len_squared_v2v2 ( fmval , mid ) ;
2009-10-07 21:19:58 +00:00
if ( d < dist ) {
side = i ;
closest = e ;
dist = d ;
}
}
}
2011-05-10 17:01:26 +00:00
2011-10-12 06:11:21 +00:00
BMBVH_FreeBVH ( bvhtree ) ;
2009-10-07 21:19:58 +00:00
EDBM_clear_flag_all ( em , BM_SELECT ) ;
2011-10-12 06:11:21 +00:00
BMO_HeaderFlag_Buffer ( bm , & bmop , side ? " edgeout2 " : " edgeout1 " , BM_SELECT , BM_EDGE ) ;
2009-10-07 21:19:58 +00:00
2011-10-12 06:11:21 +00:00
BM_ITER ( e , & iter , bm , BM_EDGES_OF_MESH , NULL ) {
2011-11-01 12:51:38 +00:00
if ( BM_TestHFlag ( e , BM_SELECT ) ) {
BM_SetHFlag ( e , BM_TMP_TAG ) ;
}
else {
BM_ClearHFlag ( e , BM_TMP_TAG ) ;
}
2009-10-07 21:19:58 +00:00
}
/*constrict edge selection again*/
2011-10-12 06:11:21 +00:00
BM_ITER ( v , & iter , bm , BM_VERTS_OF_MESH , NULL ) {
2009-10-07 21:19:58 +00:00
e2 = NULL ;
i = 0 ;
2011-10-12 06:11:21 +00:00
BM_ITER ( e , & eiter , bm , BM_EDGES_OF_VERT , v ) {
2011-11-01 12:51:38 +00:00
if ( BM_TestHFlag ( e , BM_TMP_TAG ) ) {
2009-10-07 21:19:58 +00:00
e2 = e ;
i + + ;
}
}
2009-11-04 09:37:08 +00:00
if ( i = = 1 ) {
if ( singlesel )
2011-10-12 06:11:21 +00:00
BM_Select ( bm , v , 0 ) ;
2009-11-04 09:37:08 +00:00
else
2011-10-12 06:11:21 +00:00
BM_Select ( bm , e2 , 0 ) ;
2009-11-04 09:37:08 +00:00
}
2009-10-07 21:19:58 +00:00
}
2011-10-12 06:11:21 +00:00
if ( ripvert ) {
BM_Select ( bm , ripvert , 1 ) ;
}
2009-10-07 21:19:58 +00:00
EDBM_selectmode_flush ( em ) ;
2011-10-12 06:11:21 +00:00
BLI_assert ( singlesel ? ( bm - > totvertsel > 0 ) : ( bm - > totedgesel > 0 ) ) ;
2009-10-07 21:19:58 +00:00
if ( ! EDBM_FinishOp ( em , & bmop , op , 1 ) ) {
return OPERATOR_CANCELLED ;
}
2011-10-12 06:11:21 +00:00
if ( bm - > totvertsel = = 0 ) {
return OPERATOR_CANCELLED ;
}
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-10-07 21:19:58 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
return OPERATOR_FINISHED ;
}
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 */
2010-07-19 04:44:37 +00:00
Transform_Properties ( ot , P_PROPORTIONAL ) ;
2009-10-07 21:19:58 +00:00
RNA_def_boolean ( ot - > srna , " mirror " , 0 , " Mirror Editing " , " " ) ;
2009-11-07 23:10:18 +00:00
}
/************************ Shape Operators *************************/
/*BMESH_TODO this should be properly encapsulated in a bmop. but later.*/
static void shape_propagate ( Object * obedit , BMEditMesh * em , wmOperator * op )
{
BMIter iter ;
BMVert * eve = NULL ;
float * co ;
int i , totshape = CustomData_number_of_layers ( & em - > bm - > vdata , CD_SHAPEKEY ) ;
if ( ! CustomData_has_layer ( & em - > bm - > vdata , CD_SHAPEKEY ) ) {
BKE_report ( op - > reports , RPT_ERROR , " Mesh does not have shape keys " ) ;
return ;
}
BM_ITER ( eve , & iter , em - > bm , BM_VERTS_OF_MESH , NULL ) {
if ( ! BM_TestHFlag ( eve , BM_SELECT ) | | BM_TestHFlag ( eve , BM_HIDDEN ) )
continue ;
for ( i = 0 ; i < totshape ; i + + ) {
co = CustomData_bmesh_get_n ( & em - > bm - > vdata , eve - > head . data , CD_SHAPEKEY , i ) ;
2011-09-12 05:51:35 +00:00
copy_v3_v3 ( co , eve - > co ) ;
2009-11-07 23:10:18 +00:00
}
}
#if 0
//TAG Mesh Objects that share this data
for ( base = scene - > base . first ; base ; base = base - > next ) {
if ( base - > object & & base - > object - > data = = me ) {
base - > object - > recalc = OB_RECALC_DATA ;
}
}
# endif
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2009-11-07 23:10:18 +00:00
}
static int shape_propagate_to_all_exec ( bContext * C , wmOperator * op )
{
Object * obedit = CTX_data_edit_object ( C ) ;
Mesh * me = obedit - > data ;
BMEditMesh * em = me - > edit_btmesh ;
shape_propagate ( obedit , em , op ) ;
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( & me - > id , OB_RECALC_DATA ) ;
2009-11-07 23:10:18 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , me ) ;
return OPERATOR_FINISHED ;
}
void MESH_OT_shape_propagate_to_all ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Shape Propagate " ;
2011-09-23 13:31:48 +00:00
ot - > description = " Apply selected vertex locations to all other shape keys " ;
2009-11-07 23:10:18 +00:00
ot - > idname = " MESH_OT_shape_propagate_to_all " ;
/* api callbacks */
ot - > exec = shape_propagate_to_all_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
/*BMESH_TODO this should be properly encapsulated in a bmop. but later.*/
static int blend_from_shape_exec ( bContext * C , wmOperator * op )
{
Object * obedit = CTX_data_edit_object ( C ) ;
Mesh * me = obedit - > data ;
BMEditMesh * em = me - > edit_btmesh ;
BMVert * eve ;
BMIter iter ;
float co [ 3 ] , * sco ;
float blend = RNA_float_get ( op - > ptr , " blend " ) ;
int shape = RNA_enum_get ( op - > ptr , " shape " ) ;
2011-08-20 20:19:58 +00:00
int add = RNA_boolean_get ( op - > ptr , " add " ) ;
2010-07-19 04:44:37 +00:00
int totshape ;
2009-11-07 23:10:18 +00:00
/*sanity check*/
totshape = CustomData_number_of_layers ( & em - > bm - > vdata , CD_SHAPEKEY ) ;
if ( totshape = = 0 | | shape < 0 | | shape > = totshape )
return OPERATOR_CANCELLED ;
BM_ITER ( eve , & iter , em - > bm , BM_VERTS_OF_MESH , NULL ) {
if ( ! BM_TestHFlag ( eve , BM_SELECT ) | | BM_TestHFlag ( eve , BM_HIDDEN ) )
continue ;
sco = CustomData_bmesh_get_n ( & em - > bm - > vdata , eve - > head . data , CD_SHAPEKEY , shape ) ;
2011-09-12 05:51:35 +00:00
copy_v3_v3 ( co , sco ) ;
2009-11-07 23:10:18 +00:00
if ( add ) {
2009-11-23 14:41:22 +00:00
mul_v3_fl ( co , blend ) ;
add_v3_v3v3 ( eve - > co , eve - > co , co ) ;
2009-11-07 23:10:18 +00:00
}
else
2009-11-23 14:41:22 +00:00
interp_v3_v3v3 ( eve - > co , eve - > co , co , blend ) ;
2009-11-07 23:10:18 +00:00
2011-09-12 05:51:35 +00:00
copy_v3_v3 ( sco , co ) ;
2009-11-07 23:10:18 +00:00
}
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( & me - > id , OB_RECALC_DATA ) ;
2009-11-07 23:10:18 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , me ) ;
return OPERATOR_FINISHED ;
}
2011-05-31 05:11:04 +00:00
static EnumPropertyItem * shape_itemf ( bContext * C , PointerRNA * UNUSED ( ptr ) , PropertyRNA * UNUSED ( prop ) , int * free )
2009-11-07 23:10:18 +00:00
{
Object * obedit = CTX_data_edit_object ( C ) ;
Mesh * me = ( obedit ) ? obedit - > data : NULL ;
BMEditMesh * em = me - > edit_btmesh ;
2011-09-07 06:49:20 +00:00
EnumPropertyItem * item = NULL ;
int totitem = 0 ;
2009-11-07 23:10:18 +00:00
if ( obedit & & obedit - > type = = OB_MESH & & CustomData_has_layer ( & em - > bm - > vdata , CD_SHAPEKEY ) ) {
2011-09-07 06:49:20 +00:00
EnumPropertyItem tmp = { 0 , " " , 0 , " " , " " } ;
int a ;
2009-11-07 23:10:18 +00:00
for ( a = 0 ; a < em - > bm - > vdata . totlayer ; a + + ) {
if ( em - > bm - > vdata . layers [ a ] . type ! = CD_SHAPEKEY )
continue ;
tmp . value = totitem ;
tmp . identifier = em - > bm - > vdata . layers [ a ] . name ;
tmp . name = em - > bm - > vdata . layers [ a ] . name ;
RNA_enum_item_add ( & item , & totitem , & tmp ) ;
totitem + + ;
}
}
RNA_enum_item_end ( & item , & totitem ) ;
* free = 1 ;
return item ;
}
void MESH_OT_blend_from_shape ( wmOperatorType * ot )
{
PropertyRNA * prop ;
static EnumPropertyItem shape_items [ ] = { { 0 , NULL , 0 , NULL , NULL } } ;
/* identifiers */
ot - > name = " Blend From Shape " ;
2011-09-23 13:31:48 +00:00
ot - > description = " Blend in shape from a shape key " ;
2009-11-07 23:10:18 +00:00
ot - > idname = " MESH_OT_blend_from_shape " ;
/* api callbacks */
ot - > exec = blend_from_shape_exec ;
ot - > invoke = WM_operator_props_popup ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* properties */
2011-09-23 13:31:48 +00:00
prop = RNA_def_enum ( ot - > srna , " shape " , shape_items , 0 , " Shape " , " Shape key to use for blending " ) ;
2009-11-07 23:10:18 +00:00
RNA_def_enum_funcs ( prop , shape_itemf ) ;
2011-09-23 13:31:48 +00:00
RNA_def_float ( ot - > srna , " blend " , 1.0f , - FLT_MAX , FLT_MAX , " Blend " , " Blending factor " , - 2.0f , 2.0f ) ;
RNA_def_boolean ( ot - > srna , " add " , 1 , " Add " , " Add rather then blend between shapes " ) ;
2009-11-07 23:10:18 +00:00
}
2011-08-07 12:45:55 +00:00
/* BMESH_TODO - some way to select on an arbitrary axis */
2009-11-07 23:10:18 +00:00
static int select_axis_exec ( bContext * C , wmOperator * op )
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
BMEditSelection * ese = em - > bm - > selected . last ;
2011-08-28 17:15:24 +00:00
int axis = RNA_enum_get ( op - > ptr , " axis " ) ;
2009-11-07 23:10:18 +00:00
int mode = RNA_enum_get ( op - > ptr , " mode " ) ; /* -1==aligned, 0==neg, 1==pos*/
2011-12-12 21:01:39 +00:00
if ( ese = = NULL | | ese - > htype ! = BM_VERT ) {
BKE_report ( op - > reports , RPT_WARNING , " This operator requires an active vertex (last selected) " ) ;
2009-11-07 23:10:18 +00:00
return OPERATOR_CANCELLED ;
2011-12-12 21:01:39 +00:00
}
else {
2009-11-07 23:10:18 +00:00
BMVert * ev , * act_vert = ( BMVert * ) ese - > data ;
BMIter iter ;
float value = act_vert - > co [ axis ] ;
float limit = CTX_data_tool_settings ( C ) - > doublimit ; // XXX
if ( mode = = 0 )
value - = limit ;
else if ( mode = = 1 )
value + = limit ;
BM_ITER ( ev , & iter , em - > bm , BM_VERTS_OF_MESH , NULL ) {
if ( ! BM_TestHFlag ( ev , BM_HIDDEN ) ) {
switch ( mode ) {
case - 1 : /* aligned */
if ( fabs ( ev - > co [ axis ] - value ) < limit )
BM_Select ( em - > bm , ev , 1 ) ;
break ;
case 0 : /* neg */
if ( ev - > co [ axis ] > value )
BM_Select ( em - > bm , ev , 1 ) ;
break ;
case 1 : /* pos */
if ( ev - > co [ axis ] < value )
BM_Select ( em - > bm , ev , 1 ) ;
break ;
}
}
}
}
EDBM_selectmode_flush ( em ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
return OPERATOR_FINISHED ;
}
void MESH_OT_select_axis ( wmOperatorType * ot )
{
static EnumPropertyItem axis_mode_items [ ] = {
{ 0 , " POSITIVE " , 0 , " Positive Axis " , " " } ,
{ 1 , " NEGATIVE " , 0 , " Negative Axis " , " " } ,
{ - 1 , " ALIGNED " , 0 , " Aligned Axis " , " " } ,
{ 0 , NULL , 0 , NULL , NULL } } ;
2011-08-28 17:15:24 +00:00
static EnumPropertyItem axis_items_xyz [ ] = {
{ 0 , " X_AXIS " , 0 , " X Axis " , " " } ,
{ 1 , " Y_AXIS " , 0 , " Y Axis " , " " } ,
{ 2 , " Z_AXIS " , 0 , " Z Axis " , " " } ,
{ 0 , NULL , 0 , NULL , NULL } } ;
2009-11-07 23:10:18 +00:00
/* identifiers */
ot - > name = " Select Axis " ;
2011-09-23 13:31:48 +00:00
ot - > description = " Select all data in the mesh on a single axis " ;
2009-11-07 23:10:18 +00:00
ot - > idname = " MESH_OT_select_axis " ;
/* api callbacks */
ot - > exec = select_axis_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* properties */
RNA_def_enum ( ot - > srna , " mode " , axis_mode_items , 0 , " Axis Mode " , " Axis side to use when selecting " ) ;
2011-08-28 17:15:24 +00:00
RNA_def_enum ( ot - > srna , " axis " , axis_items_xyz , 0 , " Axis " , " Select the axis to compare each vertex on " ) ;
2009-11-07 23:10:18 +00:00
}
2011-09-23 12:06:47 +00:00
static int solidify_exec ( bContext * C , wmOperator * op )
2010-01-05 22:33:41 +00:00
{
Object * obedit = CTX_data_edit_object ( C ) ;
2011-09-23 12:06:47 +00:00
Mesh * me = obedit - > data ;
BMEditMesh * em = me - > edit_btmesh ;
BMesh * bm = em - > bm ;
BMOperator bmop ;
2010-01-05 22:33:41 +00:00
float thickness = RNA_float_get ( op - > ptr , " thickness " ) ;
2011-10-10 14:56:09 +00:00
if ( ! EDBM_InitOpf ( em , & bmop , op , " solidify geom=%hf thickness=%f " , BM_SELECT , thickness ) ) {
return OPERATOR_CANCELLED ;
}
2010-01-05 22:33:41 +00:00
2011-09-23 12:06:47 +00:00
/* deselect only the faces in the region to be solidified (leave wire
edges and loose verts selected , as there will be no corresponding
geometry selected below ) */
BMO_UnHeaderFlag_Buffer ( bm , & bmop , " geom " , BM_SELECT , BM_FACE ) ;
2010-01-05 22:33:41 +00:00
2011-09-23 12:06:47 +00:00
/* run the solidify operator */
BMO_Exec_Op ( bm , & bmop ) ;
2010-01-05 22:33:41 +00:00
2011-09-23 12:06:47 +00:00
/* select the newly generated faces */
BMO_HeaderFlag_Buffer ( bm , & bmop , " geomout " , BM_SELECT , BM_FACE ) ;
2011-10-10 14:56:09 +00:00
if ( ! EDBM_FinishOp ( em , & bmop , op , 1 ) ) {
return OPERATOR_CANCELLED ;
}
2010-01-05 22:33:41 +00:00
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2010-01-05 22:33:41 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
return OPERATOR_FINISHED ;
}
void MESH_OT_solidify ( wmOperatorType * ot )
{
PropertyRNA * prop ;
/* identifiers */
ot - > name = " Solidify " ;
2011-09-23 13:31:48 +00:00
ot - > description = " Create a solid skin by extruding, compensating for sharp angles " ;
2010-01-05 22:33:41 +00:00
ot - > idname = " MESH_OT_solidify " ;
/* api callbacks */
ot - > exec = solidify_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
prop = RNA_def_float ( ot - > srna , " thickness " , 0.01f , - FLT_MAX , FLT_MAX , " thickness " , " " , - 10.0f , 10.0f ) ;
RNA_def_property_ui_range ( prop , - 10 , 10 , 0.1 , 4 ) ;
}
2010-01-28 00:45:30 +00:00
# define TRAIL_POLYLINE 1 /* For future use, They don't do anything yet */
# define TRAIL_FREEHAND 2
# define TRAIL_MIXED 3 /* (1|2) */
# define TRAIL_AUTO 4
# define TRAIL_MIDPOINTS 8
typedef struct CutCurve {
float x ;
float y ;
} CutCurve ;
/* ******************************************************************** */
/* Knife Subdivide Tool. Subdivides edges intersected by a mouse trail
drawn by user .
Currently mapped to KKey when in MeshEdit mode .
Usage :
Hit Shift K , Select Centers or Exact
Hold LMB down to draw path , hit RETKEY .
ESC cancels as expected .
Contributed by Robert Wenzlaff ( Det . Thorn ) .
2.5 revamp :
- non modal ( no menu before cutting )
- exit on mouse release
- polygon / segment drawing can become handled by WM cb later
bmesh port version
*/
# define KNIFE_EXACT 1
# define KNIFE_MIDPOINT 2
# define KNIFE_MULTICUT 3
static EnumPropertyItem knife_items [ ] = {
{ KNIFE_EXACT , " EXACT " , 0 , " Exact " , " " } ,
{ KNIFE_MIDPOINT , " MIDPOINTS " , 0 , " Midpoints " , " " } ,
{ KNIFE_MULTICUT , " MULTICUT " , 0 , " Multicut " , " " } ,
{ 0 , NULL , 0 , NULL , NULL }
} ;
/* seg_intersect() Determines if and where a mouse trail intersects an EditEdge */
static float bm_seg_intersect ( BMEdge * e , CutCurve * c , int len , char mode ,
struct GHash * gh , int * isected )
{
# define MAXSLOPE 100000
float x11 , y11 , x12 = 0 , y12 = 0 , x2max , x2min , y2max ;
float y2min , dist , lastdist = 0 , xdiff2 , xdiff1 ;
float m1 , b1 , m2 , b2 , x21 , x22 , y21 , y22 , xi ;
float yi , x1min , x1max , y1max , y1min , perc = 0 ;
float * scr ;
float threshold = 0.0 ;
int i ;
//threshold = 0.000001; /*tolerance for vertex intersection*/
// XXX threshold = scene->toolsettings->select_thresh / 100;
/* Get screen coords of verts */
scr = BLI_ghash_lookup ( gh , e - > v1 ) ;
x21 = scr [ 0 ] ;
y21 = scr [ 1 ] ;
scr = BLI_ghash_lookup ( gh , e - > v2 ) ;
x22 = scr [ 0 ] ;
y22 = scr [ 1 ] ;
xdiff2 = ( x22 - x21 ) ;
if ( xdiff2 ) {
m2 = ( y22 - y21 ) / xdiff2 ;
b2 = ( ( x22 * y21 ) - ( x21 * y22 ) ) / xdiff2 ;
}
else {
m2 = MAXSLOPE ; /* Verticle slope */
b2 = x22 ;
}
* isected = 0 ;
/*check for *exact* vertex intersection first*/
if ( mode ! = KNIFE_MULTICUT ) {
for ( i = 0 ; i < len ; i + + ) {
if ( i > 0 ) {
x11 = x12 ;
y11 = y12 ;
}
else {
x11 = c [ i ] . x ;
y11 = c [ i ] . y ;
}
x12 = c [ i ] . x ;
y12 = c [ i ] . y ;
/*test e->v1*/
if ( ( x11 = = x21 & & y11 = = y21 ) | | ( x12 = = x21 & & y12 = = y21 ) ) {
perc = 0 ;
* isected = 1 ;
return ( perc ) ;
}
/*test e->v2*/
else if ( ( x11 = = x22 & & y11 = = y22 ) | | ( x12 = = x22 & & y12 = = y22 ) ) {
perc = 0 ;
* isected = 2 ;
return ( perc ) ;
}
}
}
/*now check for edge interesect (may produce vertex intersection as well)*/
for ( i = 0 ; i < len ; i + + ) {
if ( i > 0 ) {
x11 = x12 ;
y11 = y12 ;
}
else {
x11 = c [ i ] . x ;
y11 = c [ i ] . y ;
}
x12 = c [ i ] . x ;
y12 = c [ i ] . y ;
/* Perp. Distance from point to line */
if ( m2 ! = MAXSLOPE ) dist = ( y12 - m2 * x12 - b2 ) ; /* /sqrt(m2*m2+1); Only looking for */
/* change in sign. Skip extra math */
else dist = x22 - x12 ;
if ( i = = 0 ) lastdist = dist ;
/* if dist changes sign, and intersect point in edge's Bound Box*/
if ( ( lastdist * dist ) < = 0 ) {
xdiff1 = ( x12 - x11 ) ; /* Equation of line between last 2 points */
if ( xdiff1 ) {
m1 = ( y12 - y11 ) / xdiff1 ;
b1 = ( ( x12 * y11 ) - ( x11 * y12 ) ) / xdiff1 ;
}
else {
m1 = MAXSLOPE ;
b1 = x12 ;
}
x2max = MAX2 ( x21 , x22 ) + 0.001 ; /* prevent missed edges */
x2min = MIN2 ( x21 , x22 ) - 0.001 ; /* due to round off error */
y2max = MAX2 ( y21 , y22 ) + 0.001 ;
y2min = MIN2 ( y21 , y22 ) - 0.001 ;
/* Found an intersect, calc intersect point */
if ( m1 = = m2 ) { /* co-incident lines */
/* cut at 50% of overlap area*/
x1max = MAX2 ( x11 , x12 ) ;
x1min = MIN2 ( x11 , x12 ) ;
xi = ( MIN2 ( x2max , x1max ) + MAX2 ( x2min , x1min ) ) / 2.0 ;
y1max = MAX2 ( y11 , y12 ) ;
y1min = MIN2 ( y11 , y12 ) ;
yi = ( MIN2 ( y2max , y1max ) + MAX2 ( y2min , y1min ) ) / 2.0 ;
}
else if ( m2 = = MAXSLOPE ) {
xi = x22 ;
yi = m1 * x22 + b1 ;
}
else if ( m1 = = MAXSLOPE ) {
xi = x12 ;
yi = m2 * x12 + b2 ;
}
else {
xi = ( b1 - b2 ) / ( m2 - m1 ) ;
yi = ( b1 * m2 - m1 * b2 ) / ( m2 - m1 ) ;
}
/* Intersect inside bounding box of edge?*/
if ( ( xi > = x2min ) & & ( xi < = x2max ) & & ( yi < = y2max ) & & ( yi > = y2min ) ) {
/*test for vertex intersect that may be 'close enough'*/
if ( mode ! = KNIFE_MULTICUT ) {
if ( xi < = ( x21 + threshold ) & & xi > = ( x21 - threshold ) ) {
if ( yi < = ( y21 + threshold ) & & yi > = ( y21 - threshold ) ) {
* isected = 1 ;
perc = 0 ;
break ;
}
}
if ( xi < = ( x22 + threshold ) & & xi > = ( x22 - threshold ) ) {
if ( yi < = ( y22 + threshold ) & & yi > = ( y22 - threshold ) ) {
* isected = 2 ;
perc = 0 ;
break ;
}
}
}
if ( ( m2 < = 1.0 ) & & ( m2 > = - 1.0 ) ) perc = ( xi - x21 ) / ( x22 - x21 ) ;
else perc = ( yi - y21 ) / ( y22 - y21 ) ; /*lower slope more accurate*/
//isect=32768.0*(perc+0.0000153); /* Percentage in 1/32768ths */
break ;
}
}
lastdist = dist ;
}
return ( perc ) ;
}
2010-07-22 04:54:53 +00:00
# define MAX_CUTS 2048
2010-01-28 00:45:30 +00:00
static int knife_cut_exec ( bContext * C , wmOperator * op )
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( ( Mesh * ) obedit - > data ) ) - > edit_btmesh ;
BMesh * bm = em - > bm ;
ARegion * ar = CTX_wm_region ( C ) ;
BMVert * bv ;
BMIter iter ;
BMEdge * be ;
BMOperator bmop ;
CutCurve curve [ MAX_CUTS ] ;
struct GHash * gh ;
float isect = 0.0 ;
float * scr , co [ 4 ] ;
2011-11-16 17:09:41 +00:00
int len = 0 , isected ;
2010-01-28 00:45:30 +00:00
short numcuts = 1 , mode = RNA_int_get ( op - > ptr , " type " ) ;
/* edit-object needed for matrix, and ar->regiondata for projections to work */
if ( ELEM3 ( NULL , obedit , ar , ar - > regiondata ) )
return OPERATOR_CANCELLED ;
if ( bm - > totvertsel < 2 ) {
2010-02-18 10:09:52 +00:00
//error("No edges are selected to operate on");
2010-01-28 00:45:30 +00:00
return OPERATOR_CANCELLED ; ;
}
/* get the cut curve */
RNA_BEGIN ( op - > ptr , itemptr , " path " ) {
RNA_float_get_array ( & itemptr , " loc " , ( float * ) & curve [ len ] ) ;
len + + ;
if ( len > = MAX_CUTS ) break ;
}
RNA_END ;
if ( len < 2 ) {
return OPERATOR_CANCELLED ;
}
/*the floating point coordinates of verts in screen space will be stored in a hash table according to the vertices pointer*/
2010-07-19 04:44:37 +00:00
gh = BLI_ghash_new ( BLI_ghashutil_ptrhash , BLI_ghashutil_ptrcmp , " knife cut exec " ) ;
2010-01-28 00:45:30 +00:00
for ( bv = BMIter_New ( & iter , bm , BM_VERTS_OF_MESH , NULL ) ; bv ; bv = BMIter_Step ( & iter ) ) {
scr = MEM_mallocN ( sizeof ( float ) * 2 , " Vertex Screen Coordinates " ) ;
2011-09-12 05:51:35 +00:00
copy_v3_v3 ( co , bv - > co ) ;
2010-01-28 00:45:30 +00:00
co [ 3 ] = 1.0 ;
mul_m4_v4 ( obedit - > obmat , co ) ;
project_float ( ar , co , scr ) ;
BLI_ghash_insert ( gh , bv , scr ) ;
}
2011-10-10 14:56:09 +00:00
if ( ! EDBM_InitOpf ( em , & bmop , op , " esubd " ) ) {
return OPERATOR_CANCELLED ;
}
2011-11-16 17:09:41 +00:00
2010-01-28 00:45:30 +00:00
/*store percentage of edge cut for KNIFE_EXACT here.*/
for ( be = BMIter_New ( & iter , bm , BM_EDGES_OF_MESH , NULL ) ; be ; be = BMIter_Step ( & iter ) ) {
if ( BM_Selected ( bm , be ) ) {
isect = bm_seg_intersect ( be , curve , len , mode , gh , & isected ) ;
if ( isect ! = 0.0f ) {
if ( mode ! = KNIFE_MULTICUT & & mode ! = KNIFE_MIDPOINT ) {
BMO_Insert_MapFloat ( bm , & bmop ,
" edgepercents " ,
be , isect ) ;
}
BMO_SetFlag ( bm , be , 1 ) ;
} else BMO_ClearFlag ( bm , be , 1 ) ;
} else BMO_ClearFlag ( bm , be , 1 ) ;
}
BMO_Flag_To_Slot ( bm , & bmop , " edges " , 1 , BM_EDGE ) ;
if ( mode = = KNIFE_MIDPOINT ) numcuts = 1 ;
2010-07-22 04:54:53 +00:00
BMO_Set_Int ( & bmop , " numcuts " , numcuts ) ;
BMO_Set_Int ( & bmop , " flag " , B_KNIFE ) ;
BMO_Set_Int ( & bmop , " quadcornertype " , SUBD_STRAIGHT_CUT ) ;
BMO_Set_Int ( & bmop , " singleedge " , 0 ) ;
BMO_Set_Int ( & bmop , " gridfill " , 0 ) ;
2010-01-28 00:45:30 +00:00
BMO_Set_Float ( & bmop , " radius " , 0 ) ;
BMO_Exec_Op ( bm , & bmop ) ;
2011-10-10 14:56:09 +00:00
if ( ! EDBM_FinishOp ( em , & bmop , op , 1 ) ) {
return OPERATOR_CANCELLED ;
}
2010-01-28 00:45:30 +00:00
2011-05-11 20:40:03 +00:00
BLI_ghash_free ( gh , NULL , ( GHashValFreeFP ) MEM_freeN ) ;
2010-01-28 00:45:30 +00:00
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2010-01-28 00:45:30 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
return OPERATOR_FINISHED ;
}
void MESH_OT_knife_cut ( wmOperatorType * ot )
{
PropertyRNA * prop ;
ot - > name = " Knife Cut " ;
2011-09-23 13:31:48 +00:00
ot - > description = " Cut selected edges and faces into parts " ;
2010-01-28 00:45:30 +00:00
ot - > idname = " MESH_OT_knife_cut " ;
ot - > invoke = WM_gesture_lines_invoke ;
ot - > modal = WM_gesture_lines_modal ;
ot - > exec = knife_cut_exec ;
ot - > poll = EM_view3d_poll ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
RNA_def_enum ( ot - > srna , " type " , knife_items , KNIFE_EXACT , " Type " , " " ) ;
prop = RNA_def_property ( ot - > srna , " path " , PROP_COLLECTION , PROP_NONE ) ;
RNA_def_property_struct_runtime ( prop , & RNA_OperatorMousePath ) ;
/* internal */
RNA_def_int ( ot - > srna , " cursor " , BC_KNIFECURSOR , 0 , INT_MAX , " Cursor " , " " , 0 , INT_MAX ) ;
}
2010-10-03 21:10:59 +00:00
static int mesh_separate_selected ( Main * bmain , Scene * scene , Base * editbase , wmOperator * wmop )
{
Base * basenew ;
BMIter iter ;
BMVert * v ;
BMEdge * e ;
Object * obedit = editbase - > object ;
Mesh * me = obedit - > data ;
BMEditMesh * em = me - > edit_btmesh ;
BMesh * bmnew ;
int allocsize [ ] = { 512 , 512 , 2048 , 512 } ;
if ( ! em )
return OPERATOR_CANCELLED ;
2011-03-29 05:48:18 +00:00
bmnew = BM_Make_Mesh ( obedit , allocsize ) ;
2011-03-31 00:52:12 +00:00
CustomData_copy ( & em - > bm - > vdata , & bmnew - > vdata , CD_MASK_BMESH , CD_CALLOC , 0 ) ;
CustomData_copy ( & em - > bm - > edata , & bmnew - > edata , CD_MASK_BMESH , CD_CALLOC , 0 ) ;
CustomData_copy ( & em - > bm - > ldata , & bmnew - > ldata , CD_MASK_BMESH , CD_CALLOC , 0 ) ;
CustomData_copy ( & em - > bm - > pdata , & bmnew - > pdata , CD_MASK_BMESH , CD_CALLOC , 0 ) ;
2010-10-03 21:10:59 +00:00
CustomData_bmesh_init_pool ( & bmnew - > vdata , allocsize [ 0 ] ) ;
CustomData_bmesh_init_pool ( & bmnew - > edata , allocsize [ 1 ] ) ;
CustomData_bmesh_init_pool ( & bmnew - > ldata , allocsize [ 2 ] ) ;
CustomData_bmesh_init_pool ( & bmnew - > pdata , allocsize [ 3 ] ) ;
basenew = ED_object_add_duplicate ( bmain , scene , editbase , USER_DUP_MESH ) ; /* 0 = fully linked */
assign_matarar ( basenew - > object , give_matarar ( obedit ) , * give_totcolp ( obedit ) ) ; /* new in 2.5 */
ED_base_object_select ( basenew , BA_DESELECT ) ;
EDBM_CallOpf ( em , wmop , " dupe geom=%hvef dest=%p " , BM_SELECT , bmnew ) ;
EDBM_CallOpf ( em , wmop , " del geom=%hvef context=%i " , BM_SELECT , DEL_FACES ) ;
2011-08-28 17:15:24 +00:00
2010-10-03 21:10:59 +00:00
/*clean up any loose edges*/
BM_ITER ( e , & iter , em - > bm , BM_EDGES_OF_MESH , NULL ) {
if ( BM_TestHFlag ( e , BM_HIDDEN ) )
continue ;
if ( BM_Edge_FaceCount ( e ) ! = 0 )
BM_Select ( em - > bm , e , 0 ) ; /*deselect*/
}
EDBM_CallOpf ( em , wmop , " del geom=%hvef context=%i " , BM_SELECT , DEL_EDGES ) ;
/*clean up any loose verts*/
BM_ITER ( v , & iter , em - > bm , BM_VERTS_OF_MESH , NULL ) {
if ( BM_TestHFlag ( v , BM_HIDDEN ) )
continue ;
if ( BM_Vert_EdgeCount ( v ) ! = 0 )
BM_Select ( em - > bm , v , 0 ) ; /*deselect*/
}
2011-08-28 17:15:24 +00:00
2010-10-03 21:10:59 +00:00
EDBM_CallOpf ( em , wmop , " del geom=%hvef context=%i " , BM_SELECT , DEL_VERTS ) ;
2011-09-16 05:21:24 +00:00
2010-10-03 21:10:59 +00:00
BM_Compute_Normals ( bmnew ) ;
2011-09-12 02:23:30 +00:00
BMO_CallOpf ( bmnew , " bmesh_to_mesh mesh=%p object=%p " , basenew - > object - > data , basenew - > object ) ;
2010-10-03 21:10:59 +00:00
BM_Free_Mesh ( bmnew ) ;
2011-03-31 00:52:12 +00:00
( ( Mesh * ) basenew - > object - > data ) - > edit_btmesh = NULL ;
2010-10-03 21:10:59 +00:00
return 1 ;
}
2011-05-07 02:48:14 +00:00
//BMESH_TODO
static int mesh_separate_material ( Main * UNUSED ( bmain ) , Scene * UNUSED ( scene ) , Base * UNUSED ( editbase ) , wmOperator * UNUSED ( wmop ) )
2010-10-03 21:10:59 +00:00
{
return 0 ;
}
2011-08-28 17:15:24 +00:00
static int mesh_separate_loose ( Main * bmain , Scene * scene , Base * editbase , wmOperator * wmop )
2010-10-03 21:10:59 +00:00
{
2011-08-28 17:15:24 +00:00
int i ;
BMVert * v ;
BMEdge * e ;
BMVert * v_seed ;
BMWalker walker ;
BMIter iter ;
int result = 0 ;
Object * obedit = editbase - > object ;
Mesh * me = obedit - > data ;
BMEditMesh * em = me - > edit_btmesh ;
BMesh * bm = em - > bm ;
int max_iter = bm - > totvert ;
/*Clear all selected vertices*/
BM_ITER ( v , & iter , bm , BM_VERTS_OF_MESH , NULL ) {
BM_Select ( bm , v , 0 ) ;
}
/*Flush the selection to clear edge/face selections to match
selected vertices */
EDBM_select_flush ( em , SCE_SELECT_VERTEX ) ;
/*A "while(true)" loop should work here as each iteration should
select and remove at least one vertex and when all vertices
are selected the loop will break out . But guard against bad
behavior by limiting iterations to the number of vertices in the
original mesh . */
for ( i = 0 ; i < max_iter ; i + + )
{
/* Get a seed vertex to start the walk */
v_seed = NULL ;
BM_ITER ( v , & iter , bm , BM_VERTS_OF_MESH , NULL ) {
v_seed = v ;
break ;
}
/* No vertices available, can't do anything */
if ( v_seed = = NULL )
{
break ;
}
/*Select the seed explicitly, in case it has no edges*/
BM_Select ( bm , v_seed , 1 ) ;
/*Walk from the single vertex, selecting everything connected
to it */
2011-11-24 01:07:36 +00:00
BMW_Init ( & walker , bm , BMW_SHELL , 0 , 0 , 0 , 0 , BMW_NIL_LAY ) ;
2011-08-28 17:15:24 +00:00
e = BMW_Begin ( & walker , v_seed ) ;
for ( ; e ; e = BMW_Step ( & walker ) ) {
BM_Select ( bm , e - > v1 , 1 ) ;
BM_Select ( bm , e - > v2 , 1 ) ;
}
BMW_End ( & walker ) ;
/*Flush the selection to get edge/face selections matching
the vertex selection */
EDBM_select_flush ( em , SCE_SELECT_VERTEX ) ;
if ( bm - > totvert = = bm - > totvertsel )
{
/*Every vertex selected, nothing to separate, work is done*/
break ;
}
/*Move selection into a separate object*/
result | = mesh_separate_selected ( bmain , scene , editbase , wmop ) ;
}
return result ;
2010-10-03 21:10:59 +00:00
}
2010-01-28 00:45:30 +00:00
static int mesh_separate_exec ( bContext * C , wmOperator * op )
{
2010-10-03 21:10:59 +00:00
Main * bmain = CTX_data_main ( C ) ;
2010-01-28 00:45:30 +00:00
Scene * scene = CTX_data_scene ( C ) ;
Base * base = CTX_data_active_base ( C ) ;
int retval = 0 , type = RNA_enum_get ( op - > ptr , " type " ) ;
if ( type = = 0 )
2010-10-03 21:10:59 +00:00
retval = mesh_separate_selected ( bmain , scene , base , op ) ;
2010-01-28 00:45:30 +00:00
else if ( type = = 1 )
2010-10-03 21:10:59 +00:00
retval = mesh_separate_material ( bmain , scene , base , op ) ;
2010-01-28 00:45:30 +00:00
else if ( type = = 2 )
2010-10-03 21:10:59 +00:00
retval = mesh_separate_loose ( bmain , scene , base , op ) ;
2010-01-28 00:45:30 +00:00
if ( retval ) {
2011-03-31 00:52:12 +00:00
DAG_id_tag_update ( base - > object - > data , OB_RECALC_DATA ) ;
2010-01-28 00:45:30 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , base - > object - > data ) ;
return OPERATOR_FINISHED ;
}
return OPERATOR_CANCELLED ;
}
/* *************** Operator: separate parts *************/
static EnumPropertyItem prop_separate_types [ ] = {
{ 0 , " SELECTED " , 0 , " Selection " , " " } ,
{ 1 , " MATERIAL " , 0 , " By Material " , " " } ,
{ 2 , " LOOSE " , 0 , " By loose parts " , " " } ,
{ 0 , NULL , 0 , NULL , NULL }
} ;
void MESH_OT_separate ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Separate " ;
2011-09-23 13:31:48 +00:00
ot - > description = " Separate selected geometry into a new mesh " ;
2010-01-28 00:45:30 +00:00
ot - > idname = " MESH_OT_separate " ;
/* api callbacks */
ot - > invoke = WM_menu_invoke ;
ot - > exec = mesh_separate_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
2011-12-06 18:50:45 +00:00
ot - > flag = OPTYPE_UNDO ;
2010-01-28 00:45:30 +00:00
2010-10-03 21:10:59 +00:00
ot - > prop = RNA_def_enum ( ot - > srna , " type " , prop_separate_types , 0 , " Type " , " " ) ;
2010-01-28 00:45:30 +00:00
}
static int fill_mesh_exec ( bContext * C , wmOperator * op )
{
Object * obedit = CTX_data_edit_object ( C ) ;
2011-04-23 00:05:13 +00:00
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
BMOperator bmop ;
if ( ! EDBM_InitOpf ( em , & bmop , op , " triangle_fill edges=%he " , BM_SELECT ) )
return OPERATOR_CANCELLED ;
BMO_Exec_Op ( em - > bm , & bmop ) ;
/*select new geometry*/
BMO_HeaderFlag_Buffer ( em - > bm , & bmop , " geomout " , BM_SELECT , BM_FACE | BM_EDGE ) ;
if ( ! EDBM_FinishOp ( em , & bmop , op , 1 ) )
return OPERATOR_CANCELLED ;
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2010-01-28 00:45:30 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2011-04-23 00:05:13 +00:00
2010-01-28 00:45:30 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_fill ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Fill " ;
ot - > idname = " MESH_OT_fill " ;
/* api callbacks */
ot - > exec = fill_mesh_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
2011-04-22 23:37:58 +00:00
static int beautify_fill_exec ( bContext * C , wmOperator * op )
2010-01-28 00:45:30 +00:00
{
Object * obedit = CTX_data_edit_object ( C ) ;
2011-04-22 23:37:58 +00:00
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
2010-01-28 00:45:30 +00:00
2011-04-22 23:37:58 +00:00
if ( ! EDBM_CallOpf ( em , op , " beautify_fill faces=%hf " , BM_SELECT ) )
return OPERATOR_CANCELLED ;
2010-01-28 00:45:30 +00:00
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2010-01-28 00:45:30 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2011-04-23 00:05:13 +00:00
2010-01-28 00:45:30 +00:00
return OPERATOR_FINISHED ;
}
2010-03-09 04:32:40 +00:00
void MESH_OT_beautify_fill ( wmOperatorType * ot )
2010-01-28 00:45:30 +00:00
{
/* identifiers */
2010-03-09 04:32:40 +00:00
ot - > name = " Beautify Fill " ;
ot - > idname = " MESH_OT_beautify_fill " ;
2010-01-28 00:45:30 +00:00
/* api callbacks */
2011-04-22 23:37:58 +00:00
ot - > exec = beautify_fill_exec ;
2010-01-28 00:45:30 +00:00
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
/********************** Quad/Tri Operators *************************/
static int quads_convert_to_tris_exec ( bContext * C , wmOperator * op )
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
if ( ! EDBM_CallOpf ( em , op , " triangulate faces=%hf " , BM_SELECT ) )
return OPERATOR_CANCELLED ;
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2010-01-28 00:45:30 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2010-02-18 10:09:52 +00:00
2010-01-28 00:45:30 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_quads_convert_to_tris ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Quads to Tris " ;
ot - > idname = " MESH_OT_quads_convert_to_tris " ;
/* api callbacks */
ot - > exec = quads_convert_to_tris_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
static int tris_convert_to_quads_exec ( bContext * C , wmOperator * op )
{
Object * obedit = CTX_data_edit_object ( C ) ;
2010-02-18 10:09:52 +00:00
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
int dosharp , douvs , dovcols , domaterials ;
float limit = RNA_float_get ( op - > ptr , " limit " ) ;
dosharp = RNA_boolean_get ( op - > ptr , " sharp " ) ;
douvs = RNA_boolean_get ( op - > ptr , " uvs " ) ;
dovcols = RNA_boolean_get ( op - > ptr , " vcols " ) ;
domaterials = RNA_boolean_get ( op - > ptr , " materials " ) ;
2010-01-28 00:45:30 +00:00
2010-02-18 10:09:52 +00:00
if ( ! EDBM_CallOpf ( em , op ,
" join_triangles faces=%hf limit=%f compare_sharp=%i compare_uvs=%i compare_vcols=%i compare_materials=%i " ,
BM_SELECT , limit , dosharp , douvs , dovcols , domaterials ) )
{
return OPERATOR_CANCELLED ;
}
2010-01-28 00:45:30 +00:00
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2010-01-28 00:45:30 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
return OPERATOR_FINISHED ;
}
void MESH_OT_tris_convert_to_quads ( wmOperatorType * ot )
{
2011-11-18 09:41:39 +00:00
PropertyRNA * prop ;
2010-01-28 00:45:30 +00:00
/* identifiers */
ot - > name = " Tris to Quads " ;
ot - > idname = " MESH_OT_tris_convert_to_quads " ;
/* api callbacks */
ot - > exec = tris_convert_to_quads_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2010-02-18 10:09:52 +00:00
2011-11-18 09:41:39 +00:00
prop = RNA_def_float_rotation ( ot - > srna , " limit " , 0 , NULL , 0.0f , DEG2RADF ( 180.0f ) , " Max Angle " , " Angle Limit in Degrees " , 0.0f , DEG2RADF ( 180.0f ) ) ;
RNA_def_property_float_default ( prop , DEG2RADF ( 40.0f ) ) ;
2010-02-18 10:09:52 +00:00
RNA_def_boolean ( ot - > srna , " uvs " , 0 , " Compare UVs " , " " ) ;
RNA_def_boolean ( ot - > srna , " vcols " , 0 , " Compare VCols " , " " ) ;
RNA_def_boolean ( ot - > srna , " sharp " , 0 , " Compare Sharp " , " " ) ;
RNA_def_boolean ( ot - > srna , " materials " , 0 , " Compare Materials " , " " ) ;
2010-01-28 00:45:30 +00:00
}
2011-05-07 02:48:14 +00:00
static int edge_flip_exec ( bContext * UNUSED ( C ) , wmOperator * UNUSED ( op ) )
2010-01-28 00:45:30 +00:00
{
#if 0
Object * obedit = CTX_data_edit_object ( C ) ;
EditMesh * em = BKE_mesh_get_editmesh ( ( Mesh * ) obedit - > data ) ;
edge_flip ( em ) ;
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2010-01-28 00:45:30 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
BKE_mesh_end_editmesh ( obedit - > data , em ) ;
# endif
return OPERATOR_FINISHED ;
}
void MESH_OT_edge_flip ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Edge Flip " ;
ot - > idname = " MESH_OT_edge_flip " ;
/* api callbacks */
ot - > exec = edge_flip_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
2011-09-09 14:58:49 +00:00
static int split_mesh_exec ( bContext * C , wmOperator * op )
2010-01-28 00:45:30 +00:00
{
2011-09-09 14:58:49 +00:00
Object * ob = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) ob - > data ) - > edit_btmesh ;
2011-09-16 05:21:24 +00:00
BMOperator bmop ;
2010-01-28 00:45:30 +00:00
2011-09-16 05:21:24 +00:00
EDBM_InitOpf ( em , & bmop , op , " split geom=%hvef " , BM_SELECT ) ;
BMO_Exec_Op ( em - > bm , & bmop ) ;
2011-09-09 14:58:49 +00:00
BM_clear_flag_all ( em - > bm , BM_SELECT ) ;
2011-09-16 05:21:24 +00:00
BMO_HeaderFlag_Buffer ( em - > bm , & bmop , " geomout " , BM_SELECT , BM_ALL ) ;
if ( ! EDBM_FinishOp ( em , & bmop , op , 1 ) ) {
2011-09-09 14:58:49 +00:00
return OPERATOR_CANCELLED ;
2011-09-16 05:21:24 +00:00
}
2010-01-28 00:45:30 +00:00
2011-09-09 14:58:49 +00:00
/*Geometry has changed, need to recalc normals and looptris*/
BMEdit_RecalcTesselation ( em ) ;
EDBM_RecalcNormals ( em ) ;
2010-01-28 00:45:30 +00:00
2011-09-09 14:58:49 +00:00
DAG_id_tag_update ( ob - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , ob - > data ) ;
2010-01-28 00:45:30 +00:00
2010-07-19 04:44:37 +00:00
return OPERATOR_FINISHED ;
2010-01-28 00:45:30 +00:00
}
void MESH_OT_split ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Split " ;
ot - > idname = " MESH_OT_split " ;
/* api callbacks */
2011-09-09 14:58:49 +00:00
ot - > exec = split_mesh_exec ;
2010-01-28 00:45:30 +00:00
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
2011-08-02 14:45:34 +00:00
static int spin_mesh_exec ( bContext * C , wmOperator * op )
2010-01-28 00:45:30 +00:00
{
Object * obedit = CTX_data_edit_object ( C ) ;
ToolSettings * ts = CTX_data_tool_settings ( C ) ;
2011-07-25 12:18:51 +00:00
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
2011-08-02 14:45:34 +00:00
BMesh * bm = em - > bm ;
BMOperator spinop ;
float cent [ 3 ] , axis [ 3 ] , imat [ 3 ] [ 3 ] ;
float d [ 3 ] = { 0.0f , 0.0f , 0.0f } ;
int steps , dupli ;
float degr ;
2010-01-28 00:45:30 +00:00
RNA_float_get_array ( op - > ptr , " center " , cent ) ;
2011-08-02 14:45:34 +00:00
RNA_float_get_array ( op - > ptr , " axis " , axis ) ;
steps = RNA_int_get ( op - > ptr , " steps " ) ;
degr = RNA_float_get ( op - > ptr , " degrees " ) ;
if ( ts - > editbutflag & B_CLOCKWISE ) degr = - degr ;
dupli = RNA_boolean_get ( op - > ptr , " dupli " ) ;
/* undo object transformation */
copy_m3_m4 ( imat , obedit - > imat ) ;
sub_v3_v3 ( cent , obedit - > obmat [ 3 ] ) ;
2010-01-28 00:45:30 +00:00
mul_m3_v3 ( imat , cent ) ;
2011-08-02 14:45:34 +00:00
mul_m3_v3 ( imat , axis ) ;
2010-01-28 00:45:30 +00:00
2011-10-10 14:56:09 +00:00
if ( ! EDBM_InitOpf ( em , & spinop , op ,
" spin geom=%hvef cent=%v axis=%v dvec=%v steps=%d ang=%f dupli=%d " ,
BM_SELECT , cent , axis , d , steps , degr , dupli ) ) {
return OPERATOR_CANCELLED ;
}
2011-08-02 14:45:34 +00:00
BMO_Exec_Op ( bm , & spinop ) ;
EDBM_clear_flag_all ( em , BM_SELECT ) ;
BMO_HeaderFlag_Buffer ( bm , & spinop , " lastout " , BM_SELECT , BM_ALL ) ;
2011-10-10 14:56:09 +00:00
if ( ! EDBM_FinishOp ( em , & spinop , op , 1 ) ) {
return OPERATOR_CANCELLED ;
}
2010-01-28 00:45:30 +00:00
2011-02-27 06:19:40 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
2010-01-28 00:45:30 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2011-07-25 12:18:51 +00:00
2010-01-28 00:45:30 +00:00
return OPERATOR_FINISHED ;
}
/* get center and axis, in global coords */
2011-05-07 02:48:14 +00:00
static int spin_mesh_invoke ( bContext * C , wmOperator * op , wmEvent * UNUSED ( event ) )
2010-01-28 00:45:30 +00:00
{
Scene * scene = CTX_data_scene ( C ) ;
View3D * v3d = CTX_wm_view3d ( C ) ;
RegionView3D * rv3d = ED_view3d_context_rv3d ( C ) ;
RNA_float_set_array ( op - > ptr , " center " , give_cursor ( scene , v3d ) ) ;
RNA_float_set_array ( op - > ptr , " axis " , rv3d - > viewinv [ 2 ] ) ;
2010-07-19 04:44:37 +00:00
return spin_mesh_exec ( C , op ) ;
2010-01-28 00:45:30 +00:00
}
void MESH_OT_spin ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Spin " ;
ot - > idname = " MESH_OT_spin " ;
/* api callbacks */
ot - > invoke = spin_mesh_invoke ;
ot - > exec = spin_mesh_exec ;
ot - > poll = EM_view3d_poll ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* props */
RNA_def_int ( ot - > srna , " steps " , 9 , 0 , INT_MAX , " Steps " , " Steps " , 0 , INT_MAX ) ;
RNA_def_boolean ( ot - > srna , " dupli " , 0 , " Dupli " , " Make Duplicates " ) ;
RNA_def_float ( ot - > srna , " degrees " , 90.0f , - FLT_MAX , FLT_MAX , " Degrees " , " Degrees " , - 360.0f , 360.0f ) ;
RNA_def_float_vector ( ot - > srna , " center " , 3 , NULL , - FLT_MAX , FLT_MAX , " Center " , " Center in global view space " , - FLT_MAX , FLT_MAX ) ;
RNA_def_float_vector ( ot - > srna , " axis " , 3 , NULL , - 1.0f , 1.0f , " Axis " , " Axis in global view space " , - FLT_MAX , FLT_MAX ) ;
}
2011-07-25 22:43:06 +00:00
static int screw_mesh_exec ( bContext * C , wmOperator * op )
2010-01-28 00:45:30 +00:00
{
Object * obedit = CTX_data_edit_object ( C ) ;
2011-07-25 22:43:06 +00:00
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
2011-08-02 14:45:34 +00:00
BMesh * bm = em - > bm ;
2011-07-25 22:43:06 +00:00
BMEdge * eed ;
BMVert * eve , * v1 , * v2 ;
BMIter iter , eiter ;
2011-08-02 14:45:34 +00:00
BMOperator spinop ;
float dvec [ 3 ] , nor [ 3 ] , cent [ 3 ] , axis [ 3 ] ;
float imat [ 3 ] [ 3 ] ;
2010-01-28 00:45:30 +00:00
int steps , turns ;
2011-07-25 22:43:06 +00:00
int valence ;
2010-01-28 00:45:30 +00:00
turns = RNA_int_get ( op - > ptr , " turns " ) ;
steps = RNA_int_get ( op - > ptr , " steps " ) ;
2011-08-02 14:45:34 +00:00
RNA_float_get_array ( op - > ptr , " center " , cent ) ;
RNA_float_get_array ( op - > ptr , " axis " , axis ) ;
/* undo object transformation */
copy_m3_m4 ( imat , obedit - > imat ) ;
sub_v3_v3 ( cent , obedit - > obmat [ 3 ] ) ;
mul_m3_v3 ( imat , cent ) ;
mul_m3_v3 ( imat , axis ) ;
2010-01-28 00:45:30 +00:00
2011-07-25 22:43:06 +00:00
/* find two vertices with valence count==1, more or less is wrong */
v1 = NULL ;
v2 = NULL ;
for ( eve = BMIter_New ( & iter , em - > bm , BM_VERTS_OF_MESH , NULL ) ;
eve ; eve = BMIter_Step ( & iter ) ) {
valence = 0 ;
for ( eed = BMIter_New ( & eiter , em - > bm , BM_EDGES_OF_VERT , eve ) ;
eed ; eed = BMIter_Step ( & eiter ) ) {
if ( BM_TestHFlag ( eed , BM_SELECT ) ) {
valence + + ;
2010-01-28 00:45:30 +00:00
}
2011-07-25 22:43:06 +00:00
2010-01-28 00:45:30 +00:00
}
2011-07-25 22:43:06 +00:00
if ( valence = = 1 ) {
if ( v1 = = NULL ) v1 = eve ;
2010-01-28 00:45:30 +00:00
else if ( v2 = = NULL ) v2 = eve ;
else {
v1 = NULL ;
break ;
}
}
}
2011-07-25 22:43:06 +00:00
2010-01-28 00:45:30 +00:00
if ( v1 = = NULL | | v2 = = NULL ) {
BKE_report ( op - > reports , RPT_ERROR , " You have to select a string of connected vertices too " ) ;
return OPERATOR_CANCELLED ;
}
/* calculate dvec */
2011-08-02 14:45:34 +00:00
sub_v3_v3v3 ( dvec , v1 - > co , v2 - > co ) ;
mul_v3_fl ( dvec , 1.0f / steps ) ;
2010-01-28 00:45:30 +00:00
2011-08-02 14:45:34 +00:00
if ( dot_v3v3 ( nor , dvec ) > 0.000 )
negate_v3 ( dvec ) ;
2010-01-28 00:45:30 +00:00
2011-10-10 14:56:09 +00:00
if ( ! EDBM_InitOpf ( em , & spinop , op ,
" spin geom=%hvef cent=%v axis=%v dvec=%v steps=%d ang=%f dupli=0 " ,
BM_SELECT , cent , axis , dvec , turns * steps , 360.0f * turns ) ) {
return OPERATOR_CANCELLED ;
}
2011-08-02 14:45:34 +00:00
BMO_Exec_Op ( bm , & spinop ) ;
EDBM_clear_flag_all ( em , BM_SELECT ) ;
BMO_HeaderFlag_Buffer ( bm , & spinop , " lastout " , BM_SELECT , BM_ALL ) ;
2011-10-10 14:56:09 +00:00
if ( ! EDBM_FinishOp ( em , & spinop , op , 1 ) ) {
return OPERATOR_CANCELLED ;
}
2010-01-28 00:45:30 +00:00
2011-08-02 14:45:34 +00:00
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
2011-07-25 22:43:06 +00:00
return OPERATOR_FINISHED ;
2010-01-28 00:45:30 +00:00
}
/* get center and axis, in global coords */
2011-05-07 02:48:14 +00:00
static int screw_mesh_invoke ( bContext * C , wmOperator * op , wmEvent * UNUSED ( event ) )
2010-01-28 00:45:30 +00:00
{
Scene * scene = CTX_data_scene ( C ) ;
View3D * v3d = CTX_wm_view3d ( C ) ;
RegionView3D * rv3d = ED_view3d_context_rv3d ( C ) ;
RNA_float_set_array ( op - > ptr , " center " , give_cursor ( scene , v3d ) ) ;
RNA_float_set_array ( op - > ptr , " axis " , rv3d - > viewinv [ 1 ] ) ;
2011-07-25 22:43:06 +00:00
2010-01-28 00:45:30 +00:00
return screw_mesh_exec ( C , op ) ;
}
void MESH_OT_screw ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Screw " ;
ot - > idname = " MESH_OT_screw " ;
/* api callbacks */
ot - > invoke = screw_mesh_invoke ;
ot - > exec = screw_mesh_exec ;
ot - > poll = EM_view3d_poll ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/*props */
RNA_def_int ( ot - > srna , " steps " , 9 , 0 , INT_MAX , " Steps " , " Steps " , 0 , 256 ) ;
RNA_def_int ( ot - > srna , " turns " , 1 , 0 , INT_MAX , " Turns " , " Turns " , 0 , 256 ) ;
RNA_def_float_vector ( ot - > srna , " center " , 3 , NULL , - FLT_MAX , FLT_MAX , " Center " , " Center in global view space " , - FLT_MAX , FLT_MAX ) ;
RNA_def_float_vector ( ot - > srna , " axis " , 3 , NULL , - 1.0f , 1.0f , " Axis " , " Axis in global view space " , - FLT_MAX , FLT_MAX ) ;
}
2011-06-26 20:23:27 +00:00
static int select_by_number_vertices_exec ( bContext * C , wmOperator * op )
2010-01-28 00:45:30 +00:00
{
Object * obedit = CTX_data_edit_object ( C ) ;
2011-06-26 20:23:27 +00:00
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
BMFace * efa ;
BMIter iter ;
int numverts = RNA_int_get ( op - > ptr , " number " ) ;
int type = RNA_enum_get ( op - > ptr , " type " ) ;
2010-01-28 00:45:30 +00:00
2011-06-26 20:23:27 +00:00
for ( efa = BMIter_New ( & iter , em - > bm , BM_FACES_OF_MESH , NULL ) ;
efa ; efa = BMIter_Step ( & iter ) ) {
2010-01-28 00:45:30 +00:00
2011-06-26 20:23:27 +00:00
int select = 0 ;
if ( type = = 0 & & efa - > len < numverts ) {
select = 1 ;
} else if ( type = = 1 & & efa - > len = = numverts ) {
select = 1 ;
} else if ( type = = 2 & & efa - > len > numverts ) {
select = 1 ;
2010-01-28 00:45:30 +00:00
}
2011-06-26 20:23:27 +00:00
if ( select ) {
BM_Select ( em - > bm , efa , 1 ) ;
2010-01-28 00:45:30 +00:00
}
}
2011-06-26 20:23:27 +00:00
EDBM_selectmode_flush ( em ) ;
2010-01-28 00:45:30 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_SELECT , obedit - > data ) ;
return OPERATOR_FINISHED ;
}
void MESH_OT_select_by_number_vertices ( wmOperatorType * ot )
{
2011-06-26 20:23:27 +00:00
static const EnumPropertyItem type_items [ ] = {
{ 0 , " LESS " , 0 , " Less Than " , " " } ,
{ 1 , " EQUAL " , 0 , " Equal To " , " " } ,
{ 2 , " GREATER " , 0 , " Greater Than " , " " } ,
{ 0 , NULL , 0 , NULL , NULL }
} ;
2010-01-28 00:45:30 +00:00
/* identifiers */
ot - > name = " Select by Number of Vertices " ;
2011-09-23 13:31:48 +00:00
ot - > description = " Select vertices or faces by vertex count " ;
2010-01-28 00:45:30 +00:00
ot - > idname = " MESH_OT_select_by_number_vertices " ;
/* api callbacks */
ot - > exec = select_by_number_vertices_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2011-06-26 20:23:27 +00:00
/* properties */
RNA_def_int ( ot - > srna , " number " , 4 , 3 , INT_MAX , " Number of Vertices " , " " , 3 , INT_MAX ) ;
RNA_def_enum ( ot - > srna , " type " , type_items , 1 , " Type " , " Type of comparison to make " ) ;
}
2011-07-25 10:51:24 +00:00
static int select_loose_verts_exec ( bContext * C , wmOperator * UNUSED ( op ) )
2011-06-26 20:23:27 +00:00
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
BMVert * eve ;
BMEdge * eed ;
BMIter iter ;
for ( eve = BMIter_New ( & iter , em - > bm , BM_VERTS_OF_MESH , NULL ) ;
eve ; eve = BMIter_Step ( & iter ) ) {
if ( ! eve - > e ) {
BM_Select ( em - > bm , eve , 1 ) ;
}
}
for ( eed = BMIter_New ( & iter , em - > bm , BM_EDGES_OF_MESH , NULL ) ;
eed ; eed = BMIter_Step ( & iter ) ) {
if ( ! eed - > l ) {
BM_Select ( em - > bm , eed , 1 ) ;
}
}
EDBM_selectmode_flush ( em ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_SELECT , obedit - > data ) ;
return OPERATOR_FINISHED ;
2010-01-28 00:45:30 +00:00
}
2011-06-26 20:23:27 +00:00
void MESH_OT_select_loose_verts ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Select Loose Vertices/Edges " ;
ot - > description = " Select vertices with edges or faces and edges with no faces " ;
ot - > idname = " MESH_OT_select_loose_verts " ;
/* api callbacks */
ot - > exec = select_loose_verts_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
2010-01-28 00:45:30 +00:00
2010-03-04 01:07:26 +00:00
# define MIRROR_THRESH 1.0f
2011-05-11 02:14:43 +00:00
static int select_mirror_exec ( bContext * C , wmOperator * op )
2010-01-28 00:45:30 +00:00
{
2010-03-04 01:07:26 +00:00
2010-01-28 00:45:30 +00:00
Object * obedit = CTX_data_edit_object ( C ) ;
2010-03-04 01:07:26 +00:00
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
2011-08-30 01:59:33 +00:00
BMBVHTree * tree = BMBVH_NewBVH ( em , 0 , NULL , NULL ) ;
2010-03-04 01:07:26 +00:00
BMVert * v1 , * v2 ;
BMIter iter ;
2010-01-28 00:45:30 +00:00
int extend = RNA_boolean_get ( op - > ptr , " extend " ) ;
2010-03-04 01:07:26 +00:00
float mirror_co [ 3 ] ;
BM_ITER ( v1 , & iter , em - > bm , BM_VERTS_OF_MESH , NULL ) {
2011-11-01 12:51:38 +00:00
if ( ! BM_TestHFlag ( v1 , BM_SELECT ) | | BM_TestHFlag ( v1 , BM_HIDDEN ) ) {
BM_ClearHFlag ( v1 , BM_TMP_TAG ) ;
}
else {
BM_SetHFlag ( v1 , BM_TMP_TAG ) ;
}
2010-03-04 01:07:26 +00:00
}
2010-01-28 00:45:30 +00:00
2010-03-04 01:07:26 +00:00
if ( ! extend )
EDBM_clear_flag_all ( em , BM_SELECT ) ;
BM_ITER ( v1 , & iter , em - > bm , BM_VERTS_OF_MESH , NULL ) {
2011-11-01 12:51:38 +00:00
if ( ! BM_TestHFlag ( v1 , BM_TMP_TAG ) | | BM_TestHFlag ( v1 , BM_HIDDEN ) )
2010-03-04 01:07:26 +00:00
continue ;
2011-09-12 05:51:35 +00:00
copy_v3_v3 ( mirror_co , v1 - > co ) ;
2010-03-04 01:07:26 +00:00
mirror_co [ 0 ] * = - 1.0f ;
v2 = BMBVH_FindClosestVertTopo ( tree , mirror_co , MIRROR_THRESH , v1 ) ;
if ( v2 & & ! BM_TestHFlag ( v2 , BM_HIDDEN ) )
BM_Select ( em - > bm , v2 , 1 ) ;
}
2010-01-28 00:45:30 +00:00
WM_event_add_notifier ( C , NC_GEOM | ND_SELECT , obedit - > data ) ;
return OPERATOR_FINISHED ;
}
void MESH_OT_select_mirror ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Select Mirror " ;
2011-09-23 13:31:48 +00:00
ot - > description = " Select mesh items at mirrored locations " ;
2010-01-28 00:45:30 +00:00
ot - > idname = " MESH_OT_select_mirror " ;
/* api callbacks */
ot - > exec = select_mirror_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* props */
RNA_def_boolean ( ot - > srna , " extend " , 0 , " Extend " , " Extend the existing selection " ) ;
}
2011-02-27 06:19:40 +00:00
2011-10-10 14:56:09 +00:00
#if 0 /* UNUSED */
2011-02-27 06:19:40 +00:00
/********* qsort routines. not sure how to make these
work , since we aren ' t using linked lists for
geometry anymore . might need a sortof " swap "
function for bmesh elements . * * * * * * * * */
typedef struct xvertsort {
float x ;
BMVert * v1 ;
} xvertsort ;
static int vergxco ( const void * v1 , const void * v2 )
{
const xvertsort * x1 = v1 , * x2 = v2 ;
if ( x1 - > x > x2 - > x ) return 1 ;
else if ( x1 - > x < x2 - > x ) return - 1 ;
return 0 ;
}
struct facesort {
uintptr_t x ;
struct EditFace * efa ;
} ;
static int vergface ( const void * v1 , const void * v2 )
{
const struct facesort * x1 = v1 , * x2 = v2 ;
if ( x1 - > x > x2 - > x ) return 1 ;
else if ( x1 - > x < x2 - > x ) return - 1 ;
return 0 ;
}
2011-05-09 02:45:52 +00:00
# endif
2011-02-27 06:19:40 +00:00
// XXX is this needed?
/* called from buttons */
2011-05-09 02:45:52 +00:00
#if 0 /* UNUSED */
2011-02-27 06:19:40 +00:00
static void xsortvert_flag__doSetX ( void * userData , EditVert * UNUSED ( eve ) , int x , int UNUSED ( y ) , int index )
{
xvertsort * sortblock = userData ;
sortblock [ index ] . x = x ;
}
2011-05-09 02:45:52 +00:00
# endif
2011-02-27 06:19:40 +00:00
/* all verts with (flag & 'flag') are sorted */
2011-05-07 02:48:14 +00:00
static void xsortvert_flag ( bContext * UNUSED ( C ) , int UNUSED ( flag ) )
2011-02-27 06:19:40 +00:00
{
2011-05-09 05:09:07 +00:00
/*BMESH_TODO*/
2011-02-27 06:19:40 +00:00
#if 0 //hrm, geometry isn't in linked lists anymore. . .
ViewContext vc ;
BMEditMesh * em ;
BMVert * eve ;
BMIter iter ;
xvertsort * sortblock ;
ListBase tbase ;
int i , amount ;
em_setup_viewcontext ( C , & vc ) ;
em = vc . em ;
amount = em - > bm - > totvert ;
sortblock = MEM_callocN ( sizeof ( xvertsort ) * amount , " xsort " ) ;
BM_ITER ( eve , & iter , em - > bm , BM_VERTS_OF_MESH , NULL ) {
if ( BM_TestHFlag ( eve , BM_SELECT ) )
sortblock [ i ] . v1 = eve ;
}
ED_view3d_init_mats_rv3d ( vc . obedit , vc . rv3d ) ;
2011-11-28 17:09:13 +00:00
mesh_foreachScreenVert ( & vc , xsortvert_flag__doSetX , sortblock , V3D_CLIP_TEST_OFF ) ;
2011-02-27 06:19:40 +00:00
qsort ( sortblock , amount , sizeof ( xvertsort ) , vergxco ) ;
/* make temporal listbase */
tbase . first = tbase . last = 0 ;
for ( i = 0 ; i < amount ; i + + ) {
eve = sortblock [ i ] . v1 ;
if ( eve ) {
BLI_remlink ( & vc . em - > verts , eve ) ;
BLI_addtail ( & tbase , eve ) ;
}
}
BLI_movelisttolist ( & vc . em - > verts , & tbase ) ;
MEM_freeN ( sortblock ) ;
# endif
}
static int mesh_vertices_sort_exec ( bContext * C , wmOperator * UNUSED ( op ) )
{
xsortvert_flag ( C , SELECT ) ;
return OPERATOR_FINISHED ;
}
void MESH_OT_vertices_sort ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Vertex Sort " ;
ot - > description = " Sort vertex order " ;
ot - > idname = " MESH_OT_vertices_sort " ;
/* api callbacks */
ot - > exec = mesh_vertices_sort_exec ;
ot - > poll = EM_view3d_poll ; /* uses view relative X axis to sort verts */
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
2011-10-02 15:27:30 +00:00
/* ********************** SORT FACES ******************* */
static void permutate ( void * list , int num , int size , int * index )
{
void * buf ;
int len ;
int i ;
len = num * size ;
buf = MEM_mallocN ( len , " permutate " ) ;
memcpy ( buf , list , len ) ;
for ( i = 0 ; i < num ; i + + ) {
memcpy ( ( char * ) list + ( i * size ) , ( char * ) buf + ( index [ i ] * size ) , size ) ;
}
MEM_freeN ( buf ) ;
}
/* sort faces on view axis */
static float * face_sort_floats ;
static int float_sort ( const void * v1 , const void * v2 )
{
float x1 , x2 ;
x1 = face_sort_floats [ ( ( int * ) v1 ) [ 0 ] ] ;
x2 = face_sort_floats [ ( ( int * ) v2 ) [ 0 ] ] ;
if ( x1 > x2 ) return 1 ;
else if ( x1 < x2 ) return - 1 ;
return 0 ;
}
static int sort_faces_exec ( bContext * C , wmOperator * op )
{
RegionView3D * rv3d = ED_view3d_context_rv3d ( C ) ;
View3D * v3d = CTX_wm_view3d ( C ) ;
Object * ob = CTX_data_edit_object ( C ) ;
Scene * scene = CTX_data_scene ( C ) ;
Mesh * me ;
CustomDataLayer * layer ;
int i , j , * index ;
int event ;
float reverse = 1 ;
// XXX int ctrl= 0;
if ( ! v3d ) return OPERATOR_CANCELLED ;
/* This operator work in Object Mode, not in edit mode.
* After talk with Campbell we agree that there is no point to port this to EditMesh right now .
* so for now , we just exit_editmode and enter_editmode at the end of this function .
*/
ED_object_exit_editmode ( C , EM_FREEDATA ) ;
me = ob - > data ;
if ( me - > totpoly = = 0 ) {
ED_object_enter_editmode ( C , 0 ) ;
return OPERATOR_FINISHED ;
}
event = RNA_enum_get ( op - > ptr , " type " ) ;
// XXX
//if(ctrl)
// reverse = -1;
/* create index list */
index = ( int * ) MEM_mallocN ( sizeof ( int ) * me - > totpoly , " sort faces " ) ;
for ( i = 0 ; i < me - > totpoly ; i + + ) {
index [ i ] = i ;
}
face_sort_floats = ( float * ) MEM_mallocN ( sizeof ( float ) * me - > totpoly , " sort faces float " ) ;
/* sort index list instead of faces itself
* and apply this permutation to all face layers
*/
if ( event = = 5 ) {
/* Random */
for ( i = 0 ; i < me - > totpoly ; i + + ) {
face_sort_floats [ i ] = BLI_frand ( ) ;
}
qsort ( index , me - > totpoly , sizeof ( int ) , float_sort ) ;
} else {
MPoly * mp ;
MLoop * ml ;
MVert * mv ;
float vec [ 3 ] ;
float mat [ 4 ] [ 4 ] ;
float cur [ 3 ] ;
if ( event = = 1 )
mul_m4_m4m4 ( mat , OBACT - > obmat , rv3d - > viewmat ) ; /* apply the view matrix to the object matrix */
else if ( event = = 2 ) { /* sort from cursor */
if ( v3d & & v3d - > localvd ) {
2011-10-29 06:57:50 +00:00
copy_v3_v3 ( cur , v3d - > cursor ) ;
2011-10-02 15:27:30 +00:00
} else {
2011-10-29 06:57:50 +00:00
copy_v3_v3 ( cur , scene - > cursor ) ;
2011-10-02 15:27:30 +00:00
}
invert_m4_m4 ( mat , OBACT - > obmat ) ;
mul_m4_v3 ( mat , cur ) ;
}
mp = me - > mpoly ;
for ( i = 0 ; i < me - > totpoly ; i + + , mp + + ) {
if ( event = = 3 ) {
face_sort_floats [ i ] = ( ( float ) mp - > mat_nr ) * reverse ;
} else if ( event = = 4 ) {
/*selected first*/
if ( mp - > flag & ME_FACE_SEL )
face_sort_floats [ i ] = 0.0 ;
else
face_sort_floats [ i ] = reverse ;
} else {
/* find the face's center */
ml = me - > mloop + mp - > loopstart ;
zero_v3 ( vec ) ;
for ( j = 0 ; j < mp - > totloop ; j + + , ml + + ) {
mv = me - > mvert + ml - > v ;
add_v3_v3 ( vec , mv - > co ) ;
}
mul_v3_fl ( vec , 1.0f / ( float ) mp - > totloop ) ;
if ( event = = 1 ) { /* sort on view axis */
mul_m4_v3 ( mat , vec ) ;
face_sort_floats [ i ] = vec [ 2 ] * reverse ;
} else if ( event = = 2 ) { /* distance from cursor*/
face_sort_floats [ i ] = len_v3v3 ( cur , vec ) * reverse ; /* back to front */
}
}
}
qsort ( index , me - > totpoly , sizeof ( int ) , float_sort ) ;
}
MEM_freeN ( face_sort_floats ) ;
for ( i = 0 ; i < me - > pdata . totlayer ; i + + ) {
layer = & me - > pdata . layers [ i ] ;
permutate ( layer - > data , me - > totpoly , CustomData_sizeof ( layer - > type ) , index ) ;
}
MEM_freeN ( index ) ;
DAG_id_tag_update ( ob - > data , 0 ) ;
/* Return to editmode. */
ED_object_enter_editmode ( C , 0 ) ;
return OPERATOR_FINISHED ;
}
void MESH_OT_sort_faces ( wmOperatorType * ot )
{
static EnumPropertyItem type_items [ ] = {
{ 1 , " VIEW_AXIS " , 0 , " View Axis " , " " } ,
{ 2 , " CURSOR_DISTANCE " , 0 , " Cursor Distance " , " " } ,
{ 3 , " MATERIAL " , 0 , " Material " , " " } ,
{ 4 , " SELECTED " , 0 , " Selected " , " " } ,
{ 5 , " RANDOMIZE " , 0 , " Randomize " , " " } ,
{ 0 , NULL , 0 , NULL , NULL } } ;
/* identifiers */
ot - > name = " Sort Faces " ; // XXX (Ctrl to reverse)%t|
ot - > description = " The faces of the active Mesh Object are sorted, based on the current view " ;
ot - > idname = " MESH_OT_sort_faces " ;
/* api callbacks */
ot - > invoke = WM_menu_invoke ;
ot - > exec = sort_faces_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* properties */
ot - > prop = RNA_def_enum ( ot - > srna , " type " , type_items , 0 , " Type " , " " ) ;
}
2011-02-27 06:19:40 +00:00
#if 0
/* called from buttons */
static void hashvert_flag ( EditMesh * em , int flag )
{
/* switch vertex order using hash table */
EditVert * eve ;
struct xvertsort * sortblock , * sb , onth , * newsort ;
ListBase tbase ;
int amount , a , b ;
/* count */
eve = em - > verts . first ;
amount = 0 ;
while ( eve ) {
if ( eve - > f & flag ) amount + + ;
eve = eve - > next ;
}
if ( amount = = 0 ) return ;
/* allocate memory */
sb = sortblock = ( struct xvertsort * ) MEM_mallocN ( sizeof ( struct xvertsort ) * amount , " sortremovedoub " ) ;
eve = em - > verts . first ;
while ( eve ) {
if ( eve - > f & flag ) {
sb - > v1 = eve ;
sb + + ;
}
eve = eve - > next ;
}
BLI_srand ( 1 ) ;
sb = sortblock ;
for ( a = 0 ; a < amount ; a + + , sb + + ) {
b = ( int ) ( amount * BLI_drand ( ) ) ;
if ( b > = 0 & & b < amount ) {
newsort = sortblock + b ;
onth = * sb ;
* sb = * newsort ;
* newsort = onth ;
}
}
/* make temporal listbase */
tbase . first = tbase . last = 0 ;
sb = sortblock ;
while ( amount - - ) {
eve = sb - > v1 ;
BLI_remlink ( & em - > verts , eve ) ;
BLI_addtail ( & tbase , eve ) ;
sb + + ;
}
BLI_movelisttolist ( & em - > verts , & tbase ) ;
MEM_freeN ( sortblock ) ;
}
# endif
static int mesh_vertices_randomize_exec ( bContext * C , wmOperator * UNUSED ( op ) )
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
2011-05-13 13:17:30 +00:00
# if 1 /*BMESH TODO*/
( void ) em ;
# else
2011-05-09 05:09:07 +00:00
hashvert_flag ( em , SELECT ) ;
# endif
2011-02-27 06:19:40 +00:00
return OPERATOR_FINISHED ;
}
void MESH_OT_vertices_randomize ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Vertex Randomize " ;
ot - > description = " Randomize vertex order " ;
ot - > idname = " MESH_OT_vertices_randomize " ;
/* api callbacks */
ot - > exec = mesh_vertices_randomize_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
/******end of qsort stuff ****/
static int mesh_noise_exec ( bContext * C , wmOperator * op )
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( ( Mesh * ) obedit - > data ) ) - > edit_btmesh ;
Material * ma ;
Tex * tex ;
BMVert * eve ;
BMIter iter ;
float fac = RNA_float_get ( op - > ptr , " factor " ) ;
if ( em = = NULL ) return OPERATOR_FINISHED ;
ma = give_current_material ( obedit , obedit - > actcol ) ;
if ( ma = = 0 | | ma - > mtex [ 0 ] = = 0 | | ma - > mtex [ 0 ] - > tex = = 0 ) {
2011-09-23 13:31:48 +00:00
BKE_report ( op - > reports , RPT_WARNING , " Mesh has no material or texture assigned " ) ;
2011-02-27 06:19:40 +00:00
return OPERATOR_FINISHED ;
}
tex = give_current_material_texture ( ma ) ;
if ( tex - > type = = TEX_STUCCI ) {
float b2 , vec [ 3 ] ;
float ofs = tex - > turbul / 200.0 ;
BM_ITER ( eve , & iter , em - > bm , BM_VERTS_OF_MESH , NULL ) {
if ( BM_TestHFlag ( eve , BM_SELECT ) & & ! BM_TestHFlag ( eve , BM_HIDDEN ) ) {
b2 = BLI_hnoise ( tex - > noisesize , eve - > co [ 0 ] , eve - > co [ 1 ] , eve - > co [ 2 ] ) ;
if ( tex - > stype ) ofs * = ( b2 * b2 ) ;
vec [ 0 ] = fac * ( b2 - BLI_hnoise ( tex - > noisesize , eve - > co [ 0 ] + ofs , eve - > co [ 1 ] , eve - > co [ 2 ] ) ) ;
vec [ 1 ] = fac * ( b2 - BLI_hnoise ( tex - > noisesize , eve - > co [ 0 ] , eve - > co [ 1 ] + ofs , eve - > co [ 2 ] ) ) ;
vec [ 2 ] = fac * ( b2 - BLI_hnoise ( tex - > noisesize , eve - > co [ 0 ] , eve - > co [ 1 ] , eve - > co [ 2 ] + ofs ) ) ;
add_v3_v3 ( eve - > co , vec ) ;
}
}
}
else {
BM_ITER ( eve , & iter , em - > bm , BM_VERTS_OF_MESH , NULL ) {
if ( BM_TestHFlag ( eve , BM_SELECT ) & & ! BM_TestHFlag ( eve , BM_HIDDEN ) ) {
float tin , dum ;
externtex ( ma - > mtex [ 0 ] , eve - > co , & tin , & dum , & dum , & dum , & dum , 0 ) ;
eve - > co [ 2 ] + = fac * tin ;
}
}
}
EDBM_RecalcNormals ( em ) ;
DAG_id_tag_update ( obedit - > data , 0 ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
return OPERATOR_FINISHED ;
}
void MESH_OT_noise ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Noise " ;
ot - > description = " Use vertex coordinate as texture coordinate " ;
ot - > idname = " MESH_OT_noise " ;
/* api callbacks */
ot - > exec = mesh_noise_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
RNA_def_float ( ot - > srna , " factor " , 0.1f , - FLT_MAX , FLT_MAX , " Factor " , " " , 0.0f , 1.0f ) ;
}
2011-03-17 22:59:54 +00:00
/*bevel! yay!!*/
static int mesh_bevel_exec ( bContext * C , wmOperator * op )
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( ( Mesh * ) obedit - > data ) ) - > edit_btmesh ;
BMIter iter ;
2011-04-16 13:00:41 +00:00
BMEdge * eed ;
2011-03-17 22:59:54 +00:00
BMOperator bmop ;
2011-09-07 06:49:20 +00:00
float factor = RNA_float_get ( op - > ptr , " percent " ) , fac = factor /*, dfac */ /* UNUSED */ , df , s ;
2011-04-16 13:00:41 +00:00
/*float p2 = RNA_float_get(op->ptr, "param2");
float p3 = RNA_float_get ( op - > ptr , " param3 " ) ;
float p4 = RNA_float_get ( op - > ptr , " param4 " ) ;
float p5 = RNA_float_get ( op - > ptr , " param5 " ) ; */
2011-04-24 07:45:24 +00:00
int i , recursion = RNA_int_get ( op - > ptr , " recursion " ) ;
2011-04-16 13:00:41 +00:00
float * w = NULL , ftot ;
int li ;
BLI_array_declare ( w ) ;
BM_add_data_layer ( em - > bm , & em - > bm - > edata , CD_PROP_FLT ) ;
li = CustomData_number_of_layers ( & em - > bm - > edata , CD_PROP_FLT ) - 1 ;
BM_ITER ( eed , & iter , em - > bm , BM_EDGES_OF_MESH , NULL ) {
float d = len_v3v3 ( eed - > v1 - > co , eed - > v2 - > co ) ;
float * dv = CustomData_bmesh_get_n ( & em - > bm - > edata , eed - > head . data , CD_PROP_FLT , li ) ;
* dv = d ;
}
2011-03-17 22:59:54 +00:00
if ( em = = NULL ) return OPERATOR_CANCELLED ;
2011-04-16 13:00:41 +00:00
/*ugh, stupid math depends somewhat on angles!*/
2011-09-07 06:49:20 +00:00
/* dfac = 1.0/(float)(recursion+1); */ /* UNUSED */
2011-04-16 13:00:41 +00:00
df = 1.0 ;
for ( i = 0 , ftot = 0.0f ; i < recursion ; i + + ) {
s = pow ( df , 1.25 ) ;
BLI_array_append ( w , s ) ;
ftot + = s ;
df * = 2.0 ;
}
2011-12-06 08:07:12 +00:00
mul_vn_fl ( w , BLI_array_count ( w ) , 1.0f / ( float ) ftot ) ;
2011-04-16 13:00:41 +00:00
fac = factor ;
for ( i = 0 ; i < BLI_array_count ( w ) ; i + + ) {
fac = w [ BLI_array_count ( w ) - i - 1 ] * factor ;
if ( ! EDBM_InitOpf ( em , & bmop , op , " bevel geom=%hev percent=%f lengthlayer=%i uselengths=%i " , BM_SELECT , fac , li , 1 ) )
2011-03-17 22:59:54 +00:00
return OPERATOR_CANCELLED ;
BMO_Exec_Op ( em - > bm , & bmop ) ;
2011-10-10 07:21:05 +00:00
if ( ! EDBM_FinishOp ( em , & bmop , op , 1 ) )
return OPERATOR_CANCELLED ;
2011-03-17 22:59:54 +00:00
}
2011-04-16 13:00:41 +00:00
BM_free_data_layer_n ( em - > bm , & em - > bm - > edata , CD_MASK_PROP_FLT , li ) ;
BLI_array_free ( w ) ;
2011-03-17 22:59:54 +00:00
EDBM_RecalcNormals ( em ) ;
DAG_id_tag_update ( obedit - > data , 0 ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
return OPERATOR_FINISHED ;
}
void MESH_OT_bevel ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Bevel " ;
ot - > description = " Edge/Vertex Bevel " ;
ot - > idname = " MESH_OT_bevel " ;
/* api callbacks */
ot - > exec = mesh_bevel_exec ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2011-04-16 13:00:41 +00:00
RNA_def_float ( ot - > srna , " percent " , 0.5f , - FLT_MAX , FLT_MAX , " Percentage " , " " , 0.0f , 1.0f ) ;
2011-03-17 23:06:12 +00:00
RNA_def_int ( ot - > srna , " recursion " , 1 , 1 , 50 , " Recursion Level " , " Recursion Level " , 1 , 8 ) ;
2011-04-16 13:00:41 +00:00
//RNA_def_float(ot->srna, "param2", 1.0f, -FLT_MAX, FLT_MAX, "Parameter 2", "", -1000.0f, 1000.0f);
//RNA_def_float(ot->srna, "param3", 0.5f, -FLT_MAX, FLT_MAX, "Parameter 3", "", -1000.0f, 1000.0f);
//RNA_def_float(ot->srna, "param4", 0.5f, -FLT_MAX, FLT_MAX, "Parameter 4", "", -1000.0f, 1000.0f);
//RNA_def_float(ot->srna, "param5", 0.5f, -FLT_MAX, FLT_MAX, "Parameter 5", "", -1000.0f, 1000.0f);
2011-03-17 22:59:54 +00:00
}
2011-05-02 00:58:33 +00:00
static int mesh_export_obj_exec ( bContext * C , wmOperator * op )
{
Object * ob = CTX_data_active_object ( C ) ;
DerivedMesh * dm ;
Scene * scene = CTX_data_scene ( C ) ;
Mesh * me ;
Main * bmain = CTX_data_main ( C ) ;
MVert * mvert , * mv ;
MLoop * mloop , * ml ;
MPoly * mpoly , * mp ;
MTexPoly * mtexpoly ;
MLoopUV * luv , * mloopuv ;
2011-09-16 05:21:24 +00:00
/*MLoopCol *mloopcol;*/
2011-05-02 00:58:33 +00:00
FILE * file , * matfile ;
int * face_mat_group ;
struct { Material * mat ; MTexPoly poly ; int end ; } * * matlists ;
char str [ FILE_MAX ] , str2 [ FILE_MAX ] ;
int i , j , c , free ;
if ( ob - > type ! = OB_MESH ) {
BKE_report ( op - > reports , RPT_OPERATOR , " Only meshes can be exported " ) ;
return OPERATOR_CANCELLED ;
}
RNA_string_get ( op - > ptr , " filepath " , str ) ;
sprintf ( str2 , " %s_materials.mtl " , str ) ;
file = fopen ( str , " wb " ) ;
matfile = fopen ( str2 , " wb " ) ;
if ( ! file ) {
BKE_report ( op - > reports , RPT_OPERATOR , " Could not open file " ) ;
if ( matfile )
fclose ( matfile ) ;
return OPERATOR_CANCELLED ;
}
if ( ! matfile ) {
BKE_report ( op - > reports , RPT_OPERATOR , " Could not open material file " ) ;
if ( file )
fclose ( file ) ;
return OPERATOR_CANCELLED ;
}
me = ob - > data ;
if ( me - > edit_btmesh ) {
EDBM_LoadEditBMesh ( scene , ob ) ;
}
if ( ! RNA_boolean_get ( op - > ptr , " apply_modifiers " ) ) {
dm = CDDM_from_mesh ( me , ob ) ;
free = 1 ;
} else {
dm = mesh_get_derived_final ( scene , ob , CD_MASK_DERIVEDMESH ) ;
if ( ! CDDM_Check ( dm ) ) {
dm = CDDM_copy ( dm , 0 ) ;
free = 1 ;
} else {
free = 0 ;
}
}
face_mat_group = MEM_callocN ( sizeof ( int ) * dm - > numPolyData , " face_mat_group " ) ;
if ( MAX2 ( ob - > totcol , me - > totcol ) )
matlists = MEM_callocN ( sizeof ( * matlists ) * MAX2 ( me - > totcol , ob - > totcol ) , " matlists " ) ;
else matlists = NULL ;
for ( i = 0 ; i < MAX2 ( ob - > totcol , me - > totcol ) ; i + + ) {
matlists [ i ] = MEM_callocN ( sizeof ( * * matlists ) , " matlists[i] " ) ;
matlists [ i ] [ 0 ] . end = 1 ;
}
mvert = CDDM_get_verts ( dm ) ;
mloop = CDDM_get_loops ( dm ) ;
mpoly = CDDM_get_polys ( dm ) ;
mtexpoly = CustomData_get_layer ( & dm - > polyData , CD_MTEXPOLY ) ;
mloopuv = CustomData_get_layer ( & dm - > loopData , CD_MLOOPUV ) ;
2011-09-07 06:49:20 +00:00
/* mloopcol = CustomData_get_layer(&dm->loopData, CD_MLOOPCOL); */ /* UNUSED */
2011-05-02 00:58:33 +00:00
2011-08-26 14:36:30 +00:00
if ( matlists ) {
/*build material list*/
mp = mpoly ;
for ( i = 0 ; i < dm - > numPolyData ; i + + , ( mtexpoly ? mtexpoly + + : NULL ) , mp + + ) {
int found = 0 ;
2011-05-02 00:58:33 +00:00
2011-08-26 14:36:30 +00:00
j = 0 ;
while ( ! matlists [ mp - > mat_nr ] [ j ] . end ) {
Material * mat = ob - > matbits [ mp - > mat_nr ] ? ob - > mat [ mp - > mat_nr ] : me - > mat [ mp - > mat_nr ] ;
if ( matlists [ mp - > mat_nr ] [ j ] . mat = = mat ) {
if ( mtexpoly ) {
if ( matlists [ mp - > mat_nr ] [ j ] . poly . tpage = = mtexpoly - > tpage ) {
found = 1 ;
break ;
}
} else {
2011-05-02 00:58:33 +00:00
found = 1 ;
break ;
}
}
2011-08-26 14:36:30 +00:00
j + + ;
2011-05-02 00:58:33 +00:00
}
2011-08-26 14:36:30 +00:00
if ( ! found ) {
matlists [ mp - > mat_nr ] = MEM_reallocN ( matlists [ mp - > mat_nr ] , sizeof ( * * matlists ) * ( j + 2 ) ) ;
/*add sentinal*/
matlists [ mp - > mat_nr ] [ j + 1 ] . end = 1 ;
matlists [ mp - > mat_nr ] [ j ] . end = 0 ;
if ( ob - > matbits & & ob - > matbits [ mp - > mat_nr ] ) {
matlists [ mp - > mat_nr ] [ j ] . mat = ob - > mat [ mp - > mat_nr ] ;
} else {
matlists [ mp - > mat_nr ] [ j ] . mat = me - > mat [ mp - > mat_nr ] ;
}
if ( mtexpoly )
matlists [ mp - > mat_nr ] [ j ] . poly = * mtexpoly ;
2011-05-02 00:58:33 +00:00
}
2011-08-26 14:36:30 +00:00
face_mat_group [ i ] = j ;
2011-05-02 00:58:33 +00:00
}
}
/*write material references*/
fprintf ( file , " mtllib %s_materials.mtl \n " , str ) ;
fprintf ( file , " o %s \n " , ( ob - > id . name + 2 ) ) ;
for ( mv = mvert , i = 0 ; i < dm - > numVertData ; i + + , mv + + ) {
fprintf ( file , " v %.8f \t %.8f \t %.8f \n " , mv - > co [ 0 ] , mv - > co [ 1 ] , mv - > co [ 2 ] ) ;
fprintf ( file , " vn %.5f \t %.5f \t %.5f \n " , ( float ) mv - > no [ 0 ] / 65535.0f , ( float ) mv - > no [ 1 ] / 65535.0f , ( float ) mv - > no [ 2 ] / 65535.0f ) ;
}
/*write texture coordinates*/
if ( mloopuv ) {
fprintf ( file , " \n " ) ;
for ( mp = mpoly , i = 0 ; i < dm - > numPolyData ; i + + , mp + + ) {
luv = mloopuv + mp - > loopstart ;
for ( j = 0 ; j < mp - > totloop ; j + + , luv + + ) {
fprintf ( file , " vt %.8f \t %.8f \n " , luv - > uv [ 0 ] , luv - > uv [ 1 ] ) ;
}
}
}
fprintf ( file , " \n " ) ;
c = 0 ;
for ( mp = mpoly , i = 0 ; i < dm - > numPolyData ; i + + , mp + + ) {
char matname [ 256 ] ;
if ( mp - > flag & ME_SMOOTH ) {
fprintf ( file , " s 1 \n " ) ;
} else {
fprintf ( file , " s off \n " ) ;
}
2011-08-26 14:36:30 +00:00
if ( matlists ) {
if ( matlists [ mp - > mat_nr ] [ face_mat_group [ i ] ] . mat & & matlists [ mp - > mat_nr ] [ face_mat_group [ i ] ] . poly . tpage ) {
sprintf ( matname , " %s__%s " , matlists [ mp - > mat_nr ] [ face_mat_group [ i ] ] . mat - > id . name + 2 ,
matlists [ mp - > mat_nr ] [ face_mat_group [ i ] ] . poly . tpage - > id . name + 2 ) ;
} else if ( matlists [ mp - > mat_nr ] [ face_mat_group [ i ] ] . mat ) {
sprintf ( matname , " %s " , matlists [ mp - > mat_nr ] [ face_mat_group [ i ] ] . mat - > id . name + 2 ) ;
} else if ( matlists [ mp - > mat_nr ] [ face_mat_group [ i ] ] . poly . tpage ! = NULL ) {
sprintf ( matname , " texture_%s " , matlists [ mp - > mat_nr ] [ face_mat_group [ i ] ] . poly . tpage - > id . name + 2 ) ;
} else {
sprintf ( matname , " __null_material_%d_%d " , mp - > mat_nr , face_mat_group [ mp - > mat_nr ] ) ;
}
fprintf ( file , " usemtl %s \n " , matname ) ;
2011-05-02 00:58:33 +00:00
}
fprintf ( file , " f " ) ;
ml = mloop + mp - > loopstart ;
luv = mloopuv ? mloopuv + mp - > loopstart : NULL ;
for ( j = 0 ; j < mp - > totloop ; j + + , ml + + , ( luv ? luv + + : NULL ) , c + + ) {
if ( luv ) {
fprintf ( file , " %d/%d " , ml - > v + 1 , c + 1 ) ;
} else {
fprintf ( file , " %d " , ml - > v + 1 ) ;
}
}
fprintf ( file , " \n " ) ;
}
fclose ( file ) ;
/*write material library*/
fprintf ( matfile , " #Blender MTL File \n \n " ) ;
for ( i = 0 ; i < MAX2 ( ob - > totcol , me - > totcol ) ; i + + ) {
Material * mat ;
char basedir [ FILE_MAX ] , filename [ FILE_MAX ] , str3 [ FILE_MAX ] ;
j = 0 ;
while ( ! matlists [ i ] [ j ] . end ) {
mat = matlists [ i ] [ j ] . mat ;
if ( mat & & matlists [ i ] [ j ] . poly . tpage ) {
fprintf ( matfile , " newmtl %s__%s \n " , mat - > id . name + 2 ,
matlists [ i ] [ j ] . poly . tpage - > id . name + 2 ) ;
} else if ( mat ) {
fprintf ( matfile , " newmtl %s \n " , mat - > id . name + 2 ) ;
} else if ( matlists [ i ] [ j ] . poly . tpage ! = NULL ) {
fprintf ( matfile , " newmtl texture_%s \n " , matlists [ i ] [ j ] . poly . tpage - > id . name + 2 ) ;
} else {
fprintf ( matfile , " newmtl __null_material_%d_%d \n " , i , j ) ;
}
if ( mat ) {
fprintf ( matfile , " Kd %.6f %.6f %.6f \n " , mat - > r , mat - > g , mat - > b ) ;
fprintf ( matfile , " Ks %.6f %.6f %.6f \n " , mat - > specr , mat - > specg , mat - > specb ) ;
fprintf ( matfile , " Ns %.6f \n " , mat - > spec * 1000.0f ) ;
} else {
fprintf ( matfile , " Kd %.6f %.6f %.6f \n " , 0.45f , 0.45f , 0.45f ) ;
fprintf ( matfile , " Ks %.6f %.6f %.6f \n " , 1.0f , 0.4f , 0.1f ) ;
fprintf ( matfile , " Ns %.6f \n " , 300.0f ) ;
}
fprintf ( matfile , " illum 2 \n " ) ;
if ( matlists [ i ] [ j ] . poly . tpage ) {
BLI_strncpy ( str2 , matlists [ i ] [ j ] . poly . tpage - > name , FILE_MAX ) ;
BLI_strncpy ( basedir , bmain - > name , FILE_MAX ) ;
BLI_splitdirstring ( basedir , filename ) ;
BLI_cleanup_file ( basedir , str2 ) ; /* fix any /foo/../foo/ */
if ( BLI_exists ( str2 ) ) {
char rel [ 3 ] = { 0 } ;
BLI_strncpy ( str3 , str2 , FILE_MAX ) ;
if ( RNA_boolean_get ( op - > ptr , " relpaths " ) ) {
BLI_path_rel ( str3 , str ) ;
if ( str3 [ 2 ] ! = ' . ' & & str3 [ 2 ] ! = ' / ' & & str3 [ 2 ] ! = ' \\ ' ) {
rel [ 0 ] = ' . ' ;
rel [ 1 ] = ' / ' ;
}
}
fprintf ( matfile , " map_Ka %s%s \n " , rel , ( str3 + 2 * RNA_boolean_get ( op - > ptr , " relpaths " ) ) ) ;
fprintf ( matfile , " map_Kd %s%s \n " , rel , ( str3 + 2 * RNA_boolean_get ( op - > ptr , " relpaths " ) ) ) ;
}
}
fprintf ( matfile , " \n " ) ;
j + + ;
}
}
fclose ( matfile ) ;
for ( i = 0 ; i < MAX2 ( ob - > totcol , me - > totcol ) ; i + + ) {
MEM_freeN ( matlists [ i ] ) ;
}
if ( matlists )
MEM_freeN ( matlists ) ;
if ( face_mat_group )
MEM_freeN ( face_mat_group ) ;
if ( free ) {
dm - > needsFree = 1 ;
dm - > release ( dm ) ;
}
return OPERATOR_FINISHED ;
}
static void export_obj_filesel ( bContext * C , wmOperator * op , const char * path )
{
RNA_string_set ( op - > ptr , " filepath " , path ) ;
WM_event_add_fileselect ( C , op ) ;
}
static int export_obj_invoke ( bContext * C , wmOperator * op , wmEvent * UNUSED ( event ) )
{
char filename [ FILE_MAX ] ;
BLI_strncpy ( filename , " //untitled.obj " , FILE_MAX ) ;
if ( RNA_property_is_set ( op - > ptr , " filepath " ) )
return mesh_export_obj_exec ( C , op ) ;
export_obj_filesel ( C , op , filename ) ;
return OPERATOR_RUNNING_MODAL ;
}
void EXPORT_MESH_OT_wavefront ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Export Wavefront OBJ " ;
ot - > description = " Export Wavefront (obj) " ;
ot - > idname = " EXPORT_MESH_OT_wavefront " ;
/* api callbacks */
ot - > exec = mesh_export_obj_exec ;
ot - > invoke = export_obj_invoke ;
ot - > poll = ED_operator_object_active ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* properties */
WM_operator_properties_filesel ( ot , FOLDERFILE | TEXTFILE , FILE_SPECIAL , FILE_SAVE , WM_FILESEL_FILEPATH ) ;
RNA_def_boolean ( ot - > srna , " apply_modifiers " , 0 , " Apply Modifiers " , " Apply Modifiers " ) ;
RNA_def_boolean ( ot - > srna , " relpaths " , 0 , " Relative Paths " , " Use relative paths for textures " ) ;
}
2011-08-15 23:38:51 +00:00
static int bridge_edge_loops ( bContext * C , wmOperator * op )
{
Object * obedit = CTX_data_edit_object ( C ) ;
BMEditMesh * em = ( ( Mesh * ) obedit - > data ) - > edit_btmesh ;
if ( ! EDBM_CallOpf ( em , op , " bridge_loops edges=%he " , BM_SELECT ) )
return OPERATOR_CANCELLED ;
DAG_id_tag_update ( obedit - > data , OB_RECALC_DATA ) ;
WM_event_add_notifier ( C , NC_GEOM | ND_DATA , obedit - > data ) ;
return OPERATOR_FINISHED ;
}
void MESH_OT_bridge_edge_loops ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Bridge edge loops " ;
ot - > description = " Make faces between two edge loops " ;
ot - > idname = " MESH_OT_bridge_edge_loops " ;
/* api callbacks */
ot - > exec = bridge_edge_loops ;
ot - > poll = ED_operator_editmesh ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
RNA_def_boolean ( ot - > srna , " inside " , 0 , " Inside " , " " ) ;
}