static int add_primitive_cube_exec(bContext *C, wmOperator *op) { Object *obedit; BMEditMesh *em; float loc[3], rot[3], mat[4][4], dia; bool enter_editmode; bool was_editmode; unsigned int layer; ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Cube"), &dia, mat, &was_editmode, loc, rot, layer); em = BKE_editmesh_from_object(obedit); if (!EDBM_op_call_and_selectf( em, op, "verts.out", false, "create_cube matrix=%m4 size=%f", mat, RNA_float_get(op->ptr, "radius") * 2.0f)) { return OPERATOR_CANCELLED; } /* BMESH_TODO make plane side this: M_SQRT2 - plane (diameter of 1.41 makes it unit size) */ make_prim_finish(C, obedit, was_editmode, enter_editmode); return OPERATOR_FINISHED; }
static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); BevelData *opdata; if (em->bm->totvertsel == 0) { return false; } op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator"); opdata->em = em; opdata->is_modal = is_modal; opdata->shift_factor = -1.0f; initNumInput(&opdata->num_input); opdata->num_input.flag = NUM_NO_NEGATIVE; /* avoid the cost of allocating a bm copy */ if (is_modal) { View3D *v3d = CTX_wm_view3d(C); ARegion *ar = CTX_wm_region(C); opdata->mesh_backup = EDBM_redo_state_store(em); opdata->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL); G.moving = true; opdata->twtype = v3d->twtype; v3d->twtype = 0; } return true; }
static int add_primitive_monkey_exec(bContext *C, wmOperator *op) { Object *obedit; BMEditMesh *em; float loc[3], rot[3], mat[4][4], dia; bool enter_editmode; bool is_view_aligned; unsigned int layer; bool was_editmode; ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, &is_view_aligned); if (!is_view_aligned) rot[0] += (float)M_PI / 2.0f; obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Suzanne"), &dia, mat, &was_editmode, loc, rot, layer); dia = RNA_float_get(op->ptr, "radius"); mat[0][0] *= dia; mat[1][1] *= dia; mat[2][2] *= dia; em = BKE_editmesh_from_object(obedit); if (!EDBM_op_call_and_selectf( em, op, "verts.out", false, "create_monkey matrix=%m4", mat)) { return OPERATOR_CANCELLED; } make_prim_finish(C, obedit, was_editmode, enter_editmode); return OPERATOR_FINISHED; }
/** * Special hack for MESH_OT_loopcut_slide so we get back to the selection mode */ static void transformops_loopsel_hack(bContext *C, wmOperator *op) { if (op->type->idname == OP_EDGE_SLIDE) { if (op->opm && op->opm->opm && op->opm->opm->prev) { wmOperator *op_prev = op->opm->opm->prev; Scene *scene = CTX_data_scene(C); int mesh_select_mode[3]; PropertyRNA *prop = RNA_struct_find_property(op_prev->ptr, "mesh_select_mode_init"); if (prop && RNA_property_is_set(op_prev->ptr, prop)) { ToolSettings *ts = scene->toolsettings; short selectmode_orig; RNA_property_boolean_get_array(op_prev->ptr, prop, mesh_select_mode); selectmode_orig = ((mesh_select_mode[0] ? SCE_SELECT_VERTEX : 0) | (mesh_select_mode[1] ? SCE_SELECT_EDGE : 0) | (mesh_select_mode[2] ? SCE_SELECT_FACE : 0)); /* still switch if we were originally in face select mode */ if ((ts->selectmode != selectmode_orig) && (selectmode_orig != SCE_SELECT_FACE)) { BMEditMesh *em = BKE_editmesh_from_object(scene->obedit); em->selectmode = ts->selectmode = selectmode_orig; EDBM_selectmode_set(em); } } } } }
static void make_duplis_verts(const DupliContext *ctx) { Scene *scene = ctx->scene; Object *parent = ctx->object; bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); VertexDupliData vdd; vdd.ctx = ctx; vdd.use_rotation = parent->transflag & OB_DUPLIROT; /* gather mesh info */ { Mesh *me = parent->data; BMEditMesh *em = BKE_editmesh_from_object(parent); CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO : CD_MASK_BAREMESH); if (em) vdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask); else vdd.dm = mesh_get_derived_final(scene, parent, dm_mask); vdd.edit_btmesh = me->edit_btmesh; if (use_texcoords) vdd.orco = vdd.dm->getVertDataArray(vdd.dm, CD_ORCO); else vdd.orco = NULL; vdd.totvert = vdd.dm->getNumVerts(vdd.dm); } make_child_duplis(ctx, &vdd, make_child_duplis_verts); vdd.dm->release(vdd.dm); }
static int add_primitive_cone_exec(bContext *C, wmOperator *op) { Object *obedit; BMEditMesh *em; float loc[3], rot[3], mat[4][4], dia; bool enter_editmode; unsigned int layer; bool was_editmode; const int end_fill_type = RNA_enum_get(op->ptr, "end_fill_type"); const bool cap_end = (end_fill_type != 0); const bool cap_tri = (end_fill_type == 2); ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Cone"), &dia, mat, &was_editmode, loc, rot, layer); em = BKE_editmesh_from_object(obedit); if (!EDBM_op_call_and_selectf( em, op, "verts.out", false, "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f matrix=%m4", RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius1"), RNA_float_get(op->ptr, "radius2"), cap_end, cap_tri, RNA_float_get(op->ptr, "depth"), mat)) { return OPERATOR_CANCELLED; } make_prim_finish(C, obedit, was_editmode, enter_editmode); return OPERATOR_FINISHED; }
static int add_primitive_icosphere_exec(bContext *C, wmOperator *op) { Object *obedit; BMEditMesh *em; float loc[3], rot[3], mat[4][4], dia; bool enter_editmode; bool was_editmode; unsigned int layer; ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Icosphere"), &dia, mat, &was_editmode, loc, rot, layer); em = BKE_editmesh_from_object(obedit); if (!EDBM_op_call_and_selectf( em, op, "verts.out", false, "create_icosphere subdivisions=%i diameter=%f matrix=%m4", RNA_int_get(op->ptr, "subdivisions"), RNA_float_get(op->ptr, "size"), mat)) { return OPERATOR_CANCELLED; } make_prim_finish(C, obedit, was_editmode, enter_editmode); return OPERATOR_FINISHED; }
static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) { Object *obedit = CTX_data_edit_object(C); Scene *scene = CTX_data_scene(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); BevelData *opdata; float pixels_per_inch; int i; if (em->bm->totvertsel == 0) { return false; } op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator"); opdata->em = em; opdata->is_modal = is_modal; opdata->value_mode = OFFSET_VALUE; opdata->segments = (float) RNA_int_get(op->ptr, "segments"); pixels_per_inch = U.dpi * U.pixelsize; for (i = 0; i < NUM_VALUE_KINDS; i++) { opdata->shift_value[i] = -1.0f; opdata->initial_length[i] = -1.0f; /* note: scale for OFFSET_VALUE will get overwritten in edbm_bevel_invoke */ opdata->scale[i] = value_scale_per_inch[i] / pixels_per_inch; initNumInput(&opdata->num_input[i]); opdata->num_input[i].idx_max = 0; opdata->num_input[i].val_flag[0] |= NUM_NO_NEGATIVE; if (i == SEGMENTS_VALUE) { opdata->num_input[i].val_flag[0] |= NUM_NO_FRACTION | NUM_NO_ZERO; } if (i == OFFSET_VALUE) { opdata->num_input[i].unit_sys = scene->unit.system; } opdata->num_input[i].unit_type[0] = B_UNIT_NONE; /* Not sure this is a factor or a unit? */ } /* avoid the cost of allocating a bm copy */ if (is_modal) { View3D *v3d = CTX_wm_view3d(C); ARegion *ar = CTX_wm_region(C); opdata->mesh_backup = EDBM_redo_state_store(em); opdata->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL); G.moving = G_TRANSFORM_EDIT; if (v3d) { opdata->twtype = v3d->twtype; v3d->twtype = 0; } } return true; }
static int skin_resize_poll(bContext *C) { struct Object *obedit = CTX_data_edit_object(C); if (obedit && obedit->type == OB_MESH) { BMEditMesh *em = BKE_editmesh_from_object(obedit); return (em && CustomData_has_layer(&em->bm->vdata, CD_MVERT_SKIN)); } return 0; }
/**************************** registration **********************************/ void ED_operatortypes_mesh(void) { WM_operatortype_append(MESH_OT_select_all); WM_operatortype_append(MESH_OT_select_interior_faces); WM_operatortype_append(MESH_OT_select_more); WM_operatortype_append(MESH_OT_select_less); WM_operatortype_append(MESH_OT_select_non_manifold); WM_operatortype_append(MESH_OT_select_linked); WM_operatortype_append(MESH_OT_select_linked_pick); WM_operatortype_append(MESH_OT_select_random); WM_operatortype_append(MESH_OT_select_ungrouped); WM_operatortype_append(MESH_OT_hide); WM_operatortype_append(MESH_OT_reveal); WM_operatortype_append(MESH_OT_select_face_by_sides); WM_operatortype_append(MESH_OT_select_loose); WM_operatortype_append(MESH_OT_select_mirror); WM_operatortype_append(MESH_OT_normals_make_consistent); WM_operatortype_append(MESH_OT_merge); WM_operatortype_append(MESH_OT_subdivide); WM_operatortype_append(MESH_OT_subdivide_edgering); WM_operatortype_append(MESH_OT_unsubdivide); WM_operatortype_append(MESH_OT_faces_select_linked_flat); WM_operatortype_append(MESH_OT_edges_select_sharp); WM_operatortype_append(MESH_OT_primitive_plane_add); WM_operatortype_append(MESH_OT_primitive_cube_add); WM_operatortype_append(MESH_OT_primitive_circle_add); WM_operatortype_append(MESH_OT_primitive_cylinder_add); WM_operatortype_append(MESH_OT_primitive_cone_add); WM_operatortype_append(MESH_OT_primitive_grid_add); WM_operatortype_append(MESH_OT_primitive_monkey_add); WM_operatortype_append(MESH_OT_primitive_uv_sphere_add); WM_operatortype_append(MESH_OT_primitive_ico_sphere_add); WM_operatortype_append(MESH_OT_duplicate); WM_operatortype_append(MESH_OT_remove_doubles); WM_operatortype_append(MESH_OT_spin); WM_operatortype_append(MESH_OT_screw); WM_operatortype_append(MESH_OT_extrude_region); WM_operatortype_append(MESH_OT_extrude_faces_indiv); WM_operatortype_append(MESH_OT_extrude_edges_indiv); WM_operatortype_append(MESH_OT_extrude_verts_indiv); WM_operatortype_append(MESH_OT_split); WM_operatortype_append(MESH_OT_extrude_repeat); WM_operatortype_append(MESH_OT_edge_rotate); WM_operatortype_append(MESH_OT_shortest_path_select); WM_operatortype_append(MESH_OT_loop_to_region); WM_operatortype_append(MESH_OT_region_to_loop); WM_operatortype_append(MESH_OT_select_axis); WM_operatortype_append(MESH_OT_uvs_rotate); WM_operatortype_append(MESH_OT_uvs_reverse); WM_operatortype_append(MESH_OT_colors_rotate); WM_operatortype_append(MESH_OT_colors_reverse); WM_operatortype_append(MESH_OT_fill); WM_operatortype_append(MESH_OT_fill_grid); WM_operatortype_append(MESH_OT_fill_holes); WM_operatortype_append(MESH_OT_beautify_fill); WM_operatortype_append(MESH_OT_quads_convert_to_tris); WM_operatortype_append(MESH_OT_tris_convert_to_quads); WM_operatortype_append(MESH_OT_dissolve_verts); WM_operatortype_append(MESH_OT_dissolve_edges); WM_operatortype_append(MESH_OT_dissolve_faces); WM_operatortype_append(MESH_OT_dissolve_mode); WM_operatortype_append(MESH_OT_dissolve_limited); WM_operatortype_append(MESH_OT_dissolve_degenerate); WM_operatortype_append(MESH_OT_delete_edgeloop); WM_operatortype_append(MESH_OT_faces_shade_smooth); WM_operatortype_append(MESH_OT_faces_shade_flat); WM_operatortype_append(MESH_OT_sort_elements); #ifdef WITH_FREESTYLE WM_operatortype_append(MESH_OT_mark_freestyle_face); #endif WM_operatortype_append(MESH_OT_delete); WM_operatortype_append(MESH_OT_delete_loose); WM_operatortype_append(MESH_OT_edge_collapse); WM_operatortype_append(MESH_OT_separate); WM_operatortype_append(MESH_OT_dupli_extrude_cursor); WM_operatortype_append(MESH_OT_loop_select); WM_operatortype_append(MESH_OT_edge_face_add); WM_operatortype_append(MESH_OT_shortest_path_pick); WM_operatortype_append(MESH_OT_select_similar); WM_operatortype_append(MESH_OT_select_similar_region); WM_operatortype_append(MESH_OT_select_mode); WM_operatortype_append(MESH_OT_loop_multi_select); WM_operatortype_append(MESH_OT_mark_seam); WM_operatortype_append(MESH_OT_mark_sharp); #ifdef WITH_FREESTYLE WM_operatortype_append(MESH_OT_mark_freestyle_edge); #endif WM_operatortype_append(MESH_OT_vertices_smooth); WM_operatortype_append(MESH_OT_vertices_smooth_laplacian); WM_operatortype_append(MESH_OT_noise); WM_operatortype_append(MESH_OT_flip_normals); WM_operatortype_append(MESH_OT_rip); WM_operatortype_append(MESH_OT_rip_edge); WM_operatortype_append(MESH_OT_blend_from_shape); WM_operatortype_append(MESH_OT_shape_propagate_to_all); WM_operatortype_append(MESH_OT_uv_texture_add); WM_operatortype_append(MESH_OT_uv_texture_remove); WM_operatortype_append(MESH_OT_vertex_color_add); WM_operatortype_append(MESH_OT_vertex_color_remove); WM_operatortype_append(MESH_OT_customdata_mask_clear); WM_operatortype_append(MESH_OT_customdata_skin_add); WM_operatortype_append(MESH_OT_customdata_skin_clear); WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_add); WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_clear); WM_operatortype_append(MESH_OT_drop_named_image); WM_operatortype_append(MESH_OT_edgering_select); WM_operatortype_append(MESH_OT_loopcut); WM_operatortype_append(MESH_OT_solidify); WM_operatortype_append(MESH_OT_select_nth); WM_operatortype_append(MESH_OT_vert_connect); WM_operatortype_append(MESH_OT_vert_connect_path); WM_operatortype_append(MESH_OT_vert_connect_concave); WM_operatortype_append(MESH_OT_vert_connect_nonplanar); WM_operatortype_append(MESH_OT_face_make_planar); WM_operatortype_append(MESH_OT_knife_tool); WM_operatortype_append(MESH_OT_knife_project); WM_operatortype_append(MESH_OT_bevel); WM_operatortype_append(MESH_OT_select_next_loop); WM_operatortype_append(MESH_OT_bridge_edge_loops); WM_operatortype_append(MESH_OT_inset); WM_operatortype_append(MESH_OT_offset_edge_loops); WM_operatortype_append(MESH_OT_intersect); WM_operatortype_append(MESH_OT_face_split_by_edges); WM_operatortype_append(MESH_OT_poke); WM_operatortype_append(MESH_OT_wireframe); WM_operatortype_append(MESH_OT_edge_split); #ifdef WITH_BULLET WM_operatortype_append(MESH_OT_convex_hull); #endif WM_operatortype_append(MESH_OT_bisect); WM_operatortype_append(MESH_OT_symmetrize); WM_operatortype_append(MESH_OT_symmetry_snap); #ifdef WITH_GAMEENGINE WM_operatortype_append(MESH_OT_navmesh_make); WM_operatortype_append(MESH_OT_navmesh_face_copy); WM_operatortype_append(MESH_OT_navmesh_face_add); WM_operatortype_append(MESH_OT_navmesh_reset); WM_operatortype_append(MESH_OT_navmesh_clear); #endif } #if 0 /* UNUSED, remove? */ static int ED_operator_editmesh_face_select(bContext *C) { Object *obedit = CTX_data_edit_object(C); if (obedit && obedit->type == OB_MESH) { BMEditMesh *em = BKE_editmesh_from_object(obedit); if (em && em->selectmode & SCE_SELECT_FACE) { return 1; } } return 0; }
static void rna_Scene_uvedit_aspect(Scene *scene, Object *ob, float *aspect) { if ((ob->type == OB_MESH) && (ob->mode == OB_MODE_EDIT)) { BMEditMesh *em; em = BKE_editmesh_from_object(ob); if (EDBM_mtexpoly_check(em)) { ED_uvedit_get_aspect(scene, ob, em->bm, aspect, aspect + 1); return; } } aspect[0] = aspect[1] = 1.0f; }
void ED_view3d_gizmo_mesh_preselect_get_active(bContext *C, wmGizmo *gz, Base **r_base, BMElem **r_ele) { ViewLayer *view_layer = CTX_data_view_layer(C); const int object_index = RNA_int_get(gz->ptr, "object_index"); /* weak, allocate an array just to access the index. */ Base *base = NULL; Object *obedit = NULL; { uint bases_len; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode( view_layer, CTX_wm_view3d(C), &bases_len); if (object_index < bases_len) { base = bases[object_index]; obedit = base->object; } MEM_freeN(bases); } *r_base = base; *r_ele = NULL; if (obedit) { BMEditMesh *em = BKE_editmesh_from_object(obedit); BMesh *bm = em->bm; PropertyRNA *prop; /* Ring select only defines edge, check properties exist first. */ prop = RNA_struct_find_property(gz->ptr, "vert_index"); const int vert_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1; prop = RNA_struct_find_property(gz->ptr, "edge_index"); const int edge_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1; prop = RNA_struct_find_property(gz->ptr, "face_index"); const int face_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1; if (vert_index != -1) { *r_ele = (BMElem *)BM_vert_at_index_find(bm, vert_index); } else if (edge_index != -1) { *r_ele = (BMElem *)BM_edge_at_index_find(bm, edge_index); } else if (face_index != -1) { *r_ele = (BMElem *)BM_face_at_index_find(bm, face_index); } } }
bool ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit) { if (sima && (ED_space_image_show_render(sima) || ED_space_image_show_paint(sima))) return false; if (obedit && obedit->type == OB_MESH) { struct BMEditMesh *em = BKE_editmesh_from_object(obedit); bool ret; ret = EDBM_mtexpoly_check(em); return ret; } return false; }
static void make_prim_finish(bContext *C, Object *obedit, bool was_editmode, int enter_editmode) { BMEditMesh *em = BKE_editmesh_from_object(obedit); const int exit_editmode = ((was_editmode == true) && (enter_editmode == false)); /* Primitive has all verts selected, use vert select flush * to push this up to edges & faces. */ EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX); /* only recalc editmode tessface if we are staying in editmode */ EDBM_update_generic(em, !exit_editmode, true); /* userdef */ if (exit_editmode) { ED_object_editmode_exit(C, EM_FREEDATA); /* adding EM_DO_UNDO messes up operator redo */ } WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); }
static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); int ret; if (em->bm->totedgesel == 0) { BKE_report(op->reports, RPT_ERROR, "Selected edges/faces required"); return OPERATOR_CANCELLED; } /* if the properties are set or there is no rv3d, * skip model and exec immediately */ if ((CTX_wm_region_view3d(C) == NULL) || (RNA_struct_property_is_set(op->ptr, "plane_co") && RNA_struct_property_is_set(op->ptr, "plane_no"))) { return mesh_bisect_exec(C, op); } ret = WM_gesture_straightline_invoke(C, op, event); if (ret & OPERATOR_RUNNING_MODAL) { View3D *v3d = CTX_wm_view3d(C); wmGesture *gesture = op->customdata; BisectData *opdata; opdata = MEM_mallocN(sizeof(BisectData), "inset_operator_data"); opdata->mesh_backup = EDBM_redo_state_store(em); opdata->is_first = true; gesture->userdata = opdata; /* misc other vars */ G.moving = G_TRANSFORM_EDIT; opdata->twtype = v3d->twtype; v3d->twtype = 0; /* initialize modal callout */ ED_area_headerprint(CTX_wm_area(C), IFACE_("LMB: Click and drag to draw cut line")); } return ret; }
static int knifeproject_exec(bContext *C, wmOperator *op) { ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); const bool cut_through = RNA_boolean_get(op->ptr, "cut_through"); LinkNode *polys = NULL; CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { if (ob != obedit) { polys = knifeproject_poly_from_object(ar, scene, ob, polys); } } CTX_DATA_END; if (polys) { EDBM_mesh_knife(C, polys, true, cut_through); /* select only tagged faces */ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); /* not essential, but switch out of vertex mode since the * selected regions wont be nicely isolated after flushing. * note: call after de-select to avoid selection flushing */ EDBM_selectmode_disable(scene, em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE); BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG); BM_mesh_select_mode_flush(em->bm); BLI_linklist_freeN(polys); return OPERATOR_FINISHED; } else { BKE_report(op->reports, RPT_ERROR, "No other selected objects found to use for projection"); return OPERATOR_CANCELLED; } }
static void make_duplis_faces(const DupliContext *ctx) { Scene *scene = ctx->scene; Object *parent = ctx->object; bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); FaceDupliData fdd; fdd.use_scale = ((parent->transflag & OB_DUPLIFACES_SCALE) != 0); /* gather mesh info */ { BMEditMesh *em = BKE_editmesh_from_object(parent); CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO | CD_MASK_MLOOPUV : CD_MASK_BAREMESH); if (em) fdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask); else fdd.dm = mesh_get_derived_final(scene, parent, dm_mask); if (use_texcoords) { CustomData *ml_data = fdd.dm->getLoopDataLayout(fdd.dm); const int uv_idx = CustomData_get_render_layer(ml_data, CD_MLOOPUV); fdd.orco = fdd.dm->getVertDataArray(fdd.dm, CD_ORCO); fdd.mloopuv = CustomData_get_layer_n(ml_data, CD_MLOOPUV, uv_idx); } else { fdd.orco = NULL; fdd.mloopuv = NULL; } fdd.totface = fdd.dm->getNumPolys(fdd.dm); fdd.mpoly = fdd.dm->getPolyArray(fdd.dm); fdd.mloop = fdd.dm->getLoopArray(fdd.dm); fdd.mvert = fdd.dm->getVertArray(fdd.dm); } make_child_duplis(ctx, &fdd, make_child_duplis_faces); fdd.dm->release(fdd.dm); }
static bool edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal) { InsetData *opdata; Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); if (em->bm->totvertsel == 0) { return false; } op->customdata = opdata = MEM_mallocN(sizeof(InsetData), "inset_operator_data"); opdata->old_thickness = 0.01; opdata->old_depth = 0.0; opdata->modify_depth = false; opdata->shift = false; opdata->shift_amount = 0.0f; opdata->is_modal = is_modal; opdata->em = em; initNumInput(&opdata->num_input); opdata->num_input.idx_max = 1; /* Two elements. */ opdata->num_input.unit_sys = scene->unit.system; opdata->num_input.unit_type[0] = B_UNIT_LENGTH; opdata->num_input.unit_type[1] = B_UNIT_LENGTH; if (is_modal) { View3D *v3d = CTX_wm_view3d(C); ARegion *ar = CTX_wm_region(C); opdata->mesh_backup = EDBM_redo_state_store(em); opdata->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL); G.moving = G_TRANSFORM_EDIT; opdata->twtype = v3d->twtype; v3d->twtype = 0; } return true; }
static void make_duplis_faces(const DupliContext *ctx) { Scene *scene = ctx->scene; Object *parent = ctx->object; bool for_render = ctx->eval_ctx->for_render; FaceDupliData fdd; fdd.use_scale = ((parent->transflag & OB_DUPLIFACES_SCALE) != 0); /* gather mesh info */ { BMEditMesh *em = BKE_editmesh_from_object(parent); CustomDataMask dm_mask = (for_render ? CD_MASK_BAREMESH | CD_MASK_ORCO | CD_MASK_MLOOPUV : CD_MASK_BAREMESH); if (em) fdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask); else fdd.dm = mesh_get_derived_final(scene, parent, dm_mask); if (for_render) { fdd.orco = fdd.dm->getVertDataArray(fdd.dm, CD_ORCO); fdd.mloopuv = fdd.dm->getLoopDataArray(fdd.dm, CD_MLOOPUV); } else { fdd.orco = NULL; fdd.mloopuv = NULL; } fdd.totface = fdd.dm->getNumPolys(fdd.dm); fdd.mpoly = fdd.dm->getPolyArray(fdd.dm); fdd.mloop = fdd.dm->getLoopArray(fdd.dm); fdd.mvert = fdd.dm->getVertArray(fdd.dm); } make_child_duplis(ctx, &fdd, make_child_duplis_faces); fdd.dm->release(fdd.dm); }
void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C) { Object *obedit = CTX_data_edit_object(C); uiBlock *block = uiLayoutGetBlock(layout); uiBlockSetHandleFunc(block, do_view3d_header_buttons, NULL); if (obedit && (obedit->type == OB_MESH)) { BMEditMesh *em = BKE_editmesh_from_object(obedit); uiLayout *row; row = uiLayoutRow(layout, true); block = uiLayoutGetBlock(row); uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, TIP_("Vertex select - Shift-Click for multiple modes, Ctrl-Click contracts selection")); uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, TIP_("Edge select - Shift-Click for multiple modes, Ctrl-Click expands/contracts selection")); uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, TIP_("Face select - Shift-Click for multiple modes, Ctrl-Click expands selection")); } }
static int mesh_bisect_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); /* both can be NULL, fallbacks values are used */ View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = ED_view3d_context_rv3d(C); Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); BMesh *bm; BMOperator bmop; float plane_co[3]; float plane_no[3]; float imat[4][4]; const float thresh = RNA_float_get(op->ptr, "threshold"); const bool use_fill = RNA_boolean_get(op->ptr, "use_fill"); const bool clear_inner = RNA_boolean_get(op->ptr, "clear_inner"); const bool clear_outer = RNA_boolean_get(op->ptr, "clear_outer"); PropertyRNA *prop_plane_co; PropertyRNA *prop_plane_no; prop_plane_co = RNA_struct_find_property(op->ptr, "plane_co"); if (RNA_property_is_set(op->ptr, prop_plane_co)) { RNA_property_float_get_array(op->ptr, prop_plane_co, plane_co); } else { copy_v3_v3(plane_co, ED_view3d_cursor3d_get(scene, v3d)); RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co); } prop_plane_no = RNA_struct_find_property(op->ptr, "plane_no"); if (RNA_property_is_set(op->ptr, prop_plane_no)) { RNA_property_float_get_array(op->ptr, prop_plane_no, plane_no); } else { if (rv3d) { copy_v3_v3(plane_no, rv3d->viewinv[1]); } else { /* fallback... */ plane_no[0] = plane_no[1] = 0.0f; plane_no[2] = 1.0f; } RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no); } /* -------------------------------------------------------------------- */ /* Modal support */ /* Note: keep this isolated, exec can work wihout this */ if ((op->customdata != NULL) && mesh_bisect_interactive_calc(C, op, em, plane_co, plane_no)) { /* write back to the props */ RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no); RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co); } /* End Modal */ /* -------------------------------------------------------------------- */ bm = em->bm; invert_m4_m4(imat, obedit->obmat); mul_m4_v3(imat, plane_co); mul_mat3_m4_v3(imat, plane_no); EDBM_op_init(em, &bmop, op, "bisect_plane geom=%hvef plane_co=%v plane_no=%v dist=%f clear_inner=%b clear_outer=%b", BM_ELEM_SELECT, plane_co, plane_no, thresh, clear_inner, clear_outer); BMO_op_exec(bm, &bmop); EDBM_flag_disable_all(em, BM_ELEM_SELECT); if (use_fill) { float normal_fill[3]; BMOperator bmop_fill; BMOperator bmop_attr; normalize_v3_v3(normal_fill, plane_no); if (clear_outer == true && clear_inner == false) { negate_v3(normal_fill); } /* Fill */ BMO_op_initf( bm, &bmop_fill, op->flag, "triangle_fill edges=%S normal=%v use_dissolve=%b", &bmop, "geom_cut.out", normal_fill, true); BMO_op_exec(bm, &bmop_fill); /* Copy Attributes */ BMO_op_initf(bm, &bmop_attr, op->flag, "face_attribute_fill faces=%S use_normals=%b use_data=%b", &bmop_fill, "geom.out", false, true); BMO_op_exec(bm, &bmop_attr); BMO_slot_buffer_hflag_enable(bm, bmop_fill.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true); BMO_op_finish(bm, &bmop_attr); BMO_op_finish(bm, &bmop_fill); } BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom_cut.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true); if (!EDBM_op_finish(em, &bmop, op, true)) { return OPERATOR_CANCELLED; } else { EDBM_update_generic(em, true, true); EDBM_selectmode_flush(em); return OPERATOR_FINISHED; } }
static int gizmo_preselect_edgering_test_select(bContext *C, wmGizmo *gz, const int mval[2]) { MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; struct { Object *ob; BMEdge *eed; float dist; int base_index; } best = { .dist = ED_view3d_select_dist_px(), }; struct { int base_index; int edge_index; } prev = { .base_index = gz_ring->base_index, .edge_index = gz_ring->edge_index, }; { ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); if (((gz_ring->bases)) == NULL || (gz_ring->bases[0] != view_layer->basact)) { MEM_SAFE_FREE(gz_ring->bases); gz_ring->bases = BKE_view_layer_array_from_bases_in_edit_mode( view_layer, v3d, &gz_ring->bases_len); } } ViewContext vc; em_setup_viewcontext(C, &vc); copy_v2_v2_int(vc.mval, mval); uint base_index; BMEdge *eed_test = EDBM_edge_find_nearest_ex( &vc, &best.dist, NULL, false, false, NULL, gz_ring->bases, gz_ring->bases_len, &base_index); if (eed_test) { best.ob = gz_ring->bases[base_index]->object; best.eed = eed_test; best.base_index = base_index; } BMesh *bm = NULL; if (best.eed) { gz_ring->base_index = best.base_index; bm = BKE_editmesh_from_object(gz_ring->bases[gz_ring->base_index]->object)->bm; BM_mesh_elem_index_ensure(bm, BM_EDGE); gz_ring->edge_index = BM_elem_index_get(best.eed); } else { gz_ring->base_index = -1; gz_ring->edge_index = -1; } if ((prev.base_index == gz_ring->base_index) && (prev.edge_index == gz_ring->edge_index)) { /* pass (only recalculate on change) */ } else { if (best.eed) { const float(*coords)[3] = NULL; { Object *ob = gz_ring->bases[gz_ring->base_index]->object; Depsgraph *depsgraph = CTX_data_depsgraph(C); Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data); if (me_eval->runtime.edit_data) { coords = me_eval->runtime.edit_data->vertexCos; } } EDBM_preselect_edgering_update_from_edge(gz_ring->psel, bm, best.eed, 1, coords); } else { EDBM_preselect_edgering_clear(gz_ring->psel); } RNA_int_set(gz->ptr, "object_index", gz_ring->base_index); RNA_int_set(gz->ptr, "edge_index", gz_ring->edge_index); ARegion *ar = CTX_wm_region(C); ED_region_tag_redraw(ar); } // return best.eed ? 0 : -1; return -1; } static void gizmo_preselect_edgering_setup(wmGizmo *gz) { MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; if (gz_ring->psel == NULL) { gz_ring->psel = EDBM_preselect_edgering_create(); } gz_ring->base_index = -1; }
void BKE_object_handle_data_update(EvaluationContext *eval_ctx, Scene *scene, Object *ob) { ID *data_id = (ID *)ob->data; AnimData *adt = BKE_animdata_from_id(data_id); Key *key; float ctime = BKE_scene_frame_get(scene); if (G.debug & G_DEBUG_DEPSGRAPH) printf("recalcdata %s\n", ob->id.name + 2); /* TODO(sergey): Only used by legacy depsgraph. */ if (adt) { /* evaluate drivers - datalevel */ /* XXX: for mesh types, should we push this to derivedmesh instead? */ BKE_animsys_evaluate_animdata(scene, data_id, adt, ctime, ADT_RECALC_DRIVERS); } /* TODO(sergey): Only used by legacy depsgraph. */ key = BKE_key_from_object(ob); if (key && key->block.first) { if (!(ob->shapeflag & OB_SHAPE_LOCK)) BKE_animsys_evaluate_animdata(scene, &key->id, key->adt, ctime, ADT_RECALC_DRIVERS); } /* includes all keys and modifiers */ switch (ob->type) { case OB_MESH: { BMEditMesh *em = (ob == scene->obedit) ? BKE_editmesh_from_object(ob) : NULL; uint64_t data_mask = scene->customdata_mask | CD_MASK_BAREMESH; #ifdef WITH_FREESTYLE /* make sure Freestyle edge/face marks appear in DM for render (see T40315) */ if (eval_ctx->mode != DAG_EVAL_VIEWPORT) { data_mask |= CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE; } #endif if (em) { makeDerivedMesh(scene, ob, em, data_mask, false); /* was CD_MASK_BAREMESH */ } else { makeDerivedMesh(scene, ob, NULL, data_mask, false); } break; } case OB_ARMATURE: if (ob->id.lib && ob->proxy_from) { if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) { printf("Proxy copy error, lib Object: %s proxy Object: %s\n", ob->id.name + 2, ob->proxy_from->id.name + 2); } } else { BKE_pose_where_is(scene, ob); } break; case OB_MBALL: BKE_displist_make_mball(eval_ctx, scene, ob); break; case OB_CURVE: case OB_SURF: case OB_FONT: BKE_displist_make_curveTypes(scene, ob, 0); break; case OB_LATTICE: BKE_lattice_modifiers_calc(scene, ob); break; case OB_EMPTY: if (ob->empty_drawtype == OB_EMPTY_IMAGE && ob->data) if (BKE_image_is_animated(ob->data)) BKE_image_user_check_frame_calc(ob->iuser, (int)ctime, 0); break; } /* related materials */ /* XXX: without depsgraph tagging, this will always need to be run, which will be slow! * However, not doing anything (or trying to hack around this lack) is not an option * anymore, especially due to Cycles [#31834] */ if (ob->totcol) { int a; if (ob->totcol != 0) { BLI_mutex_lock(&material_lock); for (a = 1; a <= ob->totcol; a++) { Material *ma = give_current_material(ob, a); if (ma) { /* recursively update drivers for this material */ material_drivers_update(scene, ma, ctime); } } BLI_mutex_unlock(&material_lock); } } else if (ob->type == OB_LAMP) lamp_drivers_update(scene, ob->data, ctime); /* particles */ if (ob != scene->obedit && ob->particlesystem.first) { ParticleSystem *tpsys, *psys; DerivedMesh *dm; ob->transflag &= ~OB_DUPLIPARTS; psys = ob->particlesystem.first; while (psys) { /* ensure this update always happens even if psys is disabled */ if (psys->recalc & PSYS_RECALC_TYPE) { psys_changed_type(ob, psys); } if (psys_check_enabled(ob, psys)) { /* check use of dupli objects here */ if (psys->part && (psys->part->draw_as == PART_DRAW_REND || eval_ctx->mode == DAG_EVAL_RENDER) && ((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob) || (psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group))) { ob->transflag |= OB_DUPLIPARTS; } particle_system_update(scene, ob, psys); psys = psys->next; } else if (psys->flag & PSYS_DELETE) { tpsys = psys->next; BLI_remlink(&ob->particlesystem, psys); psys_free(ob, psys); psys = tpsys; } else psys = psys->next; } if (eval_ctx->mode == DAG_EVAL_RENDER && ob->transflag & OB_DUPLIPARTS) { /* this is to make sure we get render level duplis in groups: * the derivedmesh must be created before init_render_mesh, * since object_duplilist does dupliparticles before that */ CustomDataMask data_mask = CD_MASK_BAREMESH | CD_MASK_MFACE | CD_MASK_MTFACE | CD_MASK_MCOL; dm = mesh_create_derived_render(scene, ob, data_mask); dm->release(dm); for (psys = ob->particlesystem.first; psys; psys = psys->next) psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated; } } /* quick cache removed */ }
static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) { Scene *scene = CTX_data_scene(C); BevelData *opdata; ViewLayer *view_layer = CTX_data_view_layer(C); float pixels_per_inch; int i, otype; if (is_modal) { RNA_float_set(op->ptr, "offset", 0.0f); RNA_float_set(op->ptr, "offset_pct", 0.0f); } op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator"); uint objects_used_len = 0; opdata->max_obj_scale = FLT_MIN; { uint ob_store_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( view_layer, CTX_wm_view3d(C), &ob_store_len); opdata->ob_store = MEM_malloc_arrayN(ob_store_len, sizeof(*opdata->ob_store), __func__); for (uint ob_index = 0; ob_index < ob_store_len; ob_index++) { Object *obedit = objects[ob_index]; float scale = mat4_to_scale(obedit->obmat); opdata->max_obj_scale = max_ff(opdata->max_obj_scale, scale); BMEditMesh *em = BKE_editmesh_from_object(obedit); if (em->bm->totvertsel > 0) { opdata->ob_store[objects_used_len].em = em; objects_used_len++; } } MEM_freeN(objects); opdata->ob_store_len = objects_used_len; } opdata->is_modal = is_modal; otype = RNA_enum_get(op->ptr, "offset_type"); opdata->value_mode = (otype == BEVEL_AMT_PERCENT) ? OFFSET_VALUE_PERCENT : OFFSET_VALUE; opdata->segments = (float)RNA_int_get(op->ptr, "segments"); pixels_per_inch = U.dpi * U.pixelsize; for (i = 0; i < NUM_VALUE_KINDS; i++) { opdata->shift_value[i] = -1.0f; opdata->initial_length[i] = -1.0f; /* note: scale for OFFSET_VALUE will get overwritten in edbm_bevel_invoke */ opdata->scale[i] = value_scale_per_inch[i] / pixels_per_inch; initNumInput(&opdata->num_input[i]); opdata->num_input[i].idx_max = 0; opdata->num_input[i].val_flag[0] |= NUM_NO_NEGATIVE; if (i == SEGMENTS_VALUE) { opdata->num_input[i].val_flag[0] |= NUM_NO_FRACTION | NUM_NO_ZERO; } if (i == OFFSET_VALUE) { opdata->num_input[i].unit_sys = scene->unit.system; } /* Not sure this is a factor or a unit? */ opdata->num_input[i].unit_type[0] = B_UNIT_NONE; } /* avoid the cost of allocating a bm copy */ if (is_modal) { View3D *v3d = CTX_wm_view3d(C); ARegion *ar = CTX_wm_region(C); for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { opdata->ob_store[ob_index].mesh_backup = EDBM_redo_state_store( opdata->ob_store[ob_index].em); } opdata->draw_handle_pixel = ED_region_draw_cb_activate( ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL); G.moving = G_TRANSFORM_EDIT; if (v3d) { opdata->gizmo_flag = v3d->gizmo_flag; v3d->gizmo_flag = V3D_GIZMO_HIDE; } } return true; }
static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int mval[2]) { MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; struct { Object *ob; BMElem *ele; float dist; int base_index; } best = { .dist = ED_view3d_select_dist_px(), }; struct { int base_index; int vert_index; int edge_index; int face_index; } prev = { .base_index = gz_ele->base_index, .vert_index = gz_ele->vert_index, .edge_index = gz_ele->edge_index, .face_index = gz_ele->face_index, }; { ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); if (((gz_ele->bases)) == NULL || (gz_ele->bases[0] != view_layer->basact)) { MEM_SAFE_FREE(gz_ele->bases); gz_ele->bases = BKE_view_layer_array_from_bases_in_edit_mode( view_layer, v3d, &gz_ele->bases_len); } } ViewContext vc; em_setup_viewcontext(C, &vc); copy_v2_v2_int(vc.mval, mval); { /* TODO: support faces. */ int base_index = -1; BMVert *eve_test; BMEdge *eed_test; if (EDBM_unified_findnearest_from_raycast(&vc, gz_ele->bases, gz_ele->bases_len, true, &base_index, &eve_test, &eed_test, NULL)) { Base *base = gz_ele->bases[base_index]; best.ob = base->object; if (eve_test) { best.ele = (BMElem *)eve_test; } else if (eed_test) { best.ele = (BMElem *)eed_test; } else { BLI_assert(0); } best.base_index = base_index; /* Check above should never fail, if it does it's an internal error. */ BLI_assert(best.base_index != -1); } } BMesh *bm = NULL; gz_ele->base_index = -1; gz_ele->vert_index = -1; gz_ele->edge_index = -1; gz_ele->face_index = -1; if (best.ele) { gz_ele->base_index = best.base_index; bm = BKE_editmesh_from_object(gz_ele->bases[gz_ele->base_index]->object)->bm; BM_mesh_elem_index_ensure(bm, best.ele->head.htype); if (best.ele->head.htype == BM_VERT) { gz_ele->vert_index = BM_elem_index_get(best.ele); } else if (best.ele->head.htype == BM_EDGE) { gz_ele->edge_index = BM_elem_index_get(best.ele); } else if (best.ele->head.htype == BM_FACE) { gz_ele->face_index = BM_elem_index_get(best.ele); } } if ((prev.base_index == gz_ele->base_index) && (prev.vert_index == gz_ele->vert_index) && (prev.edge_index == gz_ele->edge_index) && (prev.face_index == gz_ele->face_index)) { /* pass (only recalculate on change) */ } else { if (best.ele) { const float(*coords)[3] = NULL; { Object *ob = gz_ele->bases[gz_ele->base_index]->object; Depsgraph *depsgraph = CTX_data_depsgraph(C); Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data); if (me_eval->runtime.edit_data) { coords = me_eval->runtime.edit_data->vertexCos; } } EDBM_preselect_elem_update_from_single(gz_ele->psel, bm, best.ele, coords); } else { EDBM_preselect_elem_clear(gz_ele->psel); } RNA_int_set(gz->ptr, "object_index", gz_ele->base_index); RNA_int_set(gz->ptr, "vert_index", gz_ele->vert_index); RNA_int_set(gz->ptr, "edge_index", gz_ele->edge_index); RNA_int_set(gz->ptr, "face_index", gz_ele->face_index); ARegion *ar = CTX_wm_region(C); ED_region_tag_redraw(ar); } // return best.eed ? 0 : -1; return -1; } static void gizmo_preselect_elem_setup(wmGizmo *gz) { MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; if (gz_ele->psel == NULL) { gz_ele->psel = EDBM_preselect_elem_create(); } gz_ele->base_index = -1; }