Edit Mesh: Poly build tool improvements
This commit changes the functionality of the Poly build tool to make it more suitable for retopology tasks: - Click and drag from a boundary edge extrudes a new quad - Click and drag on vertices tweaks the position - Ctrl + click adds geometry. There is a geometry preview in the gizmo. It also can automatically convert triangles to quads. - Shift + click deletes mesh elements (faces or vertices) - Updated preselection code. Different mesh elements take priority depending on the selected action. Reviewed By: campbellbarton Differential Revision: https://developer.blender.org/D5573
This commit is contained in:
@@ -5454,11 +5454,11 @@ def km_3d_view_tool_edit_mesh_poly_build(params):
|
||||
"3D View Tool: Edit Mesh, Poly Build",
|
||||
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
|
||||
{"items": [
|
||||
("mesh.polybuild_face_at_cursor_move", {"type": params.tool_mouse, "value": 'PRESS'},
|
||||
("mesh.polybuild_extrude_at_cursor_move", {"type": params.tool_mouse, "value": 'PRESS'},
|
||||
{"properties": [("TRANSFORM_OT_translate", [("release_confirm", True)])]}),
|
||||
("mesh.polybuild_split_at_cursor_move", {"type": params.tool_mouse, "value": 'PRESS', "ctrl": True},
|
||||
("mesh.polybuild_face_at_cursor_move", {"type": params.tool_mouse, "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("TRANSFORM_OT_translate", [("release_confirm", True)])]}),
|
||||
("mesh.polybuild_dissolve_at_cursor", {"type": params.tool_mouse, "value": 'CLICK', "alt": True}, None),
|
||||
("mesh.polybuild_delete_at_cursor", {"type": params.tool_mouse, "value": 'CLICK', "shift": True}, None),
|
||||
]},
|
||||
)
|
||||
|
||||
|
||||
@@ -490,12 +490,17 @@ class _defs_edit_mesh:
|
||||
|
||||
@ToolDef.from_fn
|
||||
def poly_build():
|
||||
def draw_settings(context, layout, tool):
|
||||
props = tool.operator_properties("mesh.polybuild_face_at_cursor_move")
|
||||
props_macro = props.MESH_OT_polybuild_face_at_cursor
|
||||
layout.prop(props_macro, "create_quads")
|
||||
return dict(
|
||||
idname="builtin.poly_build",
|
||||
label="Poly Build",
|
||||
icon="ops.mesh.polybuild_hover",
|
||||
widget="VIEW3D_GGT_mesh_preselect_elem",
|
||||
keymap=(),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
|
||||
@@ -194,8 +194,11 @@ bool EDBM_unified_findnearest(struct ViewContext *vc,
|
||||
bool EDBM_unified_findnearest_from_raycast(struct ViewContext *vc,
|
||||
struct Base **bases,
|
||||
const uint bases_len,
|
||||
bool use_boundary,
|
||||
int *r_base_index,
|
||||
bool use_boundary_vertices,
|
||||
bool use_boundary_edges,
|
||||
int *r_base_index_vert,
|
||||
int *r_base_index_edge,
|
||||
int *r_base_index_face,
|
||||
struct BMVert **r_eve,
|
||||
struct BMEdge **r_eed,
|
||||
struct BMFace **r_efa);
|
||||
@@ -245,15 +248,30 @@ void EDBM_preselect_edgering_update_from_edge(struct EditMesh_PreSelEdgeRing *ps
|
||||
|
||||
/* editmesh_preselect_elem.c */
|
||||
struct EditMesh_PreSelElem;
|
||||
typedef enum eEditMesh_PreSelPreviewAction {
|
||||
PRESELECT_ACTION_TRANSFORM = 1,
|
||||
PRESELECT_ACTION_CREATE = 2,
|
||||
PRESELECT_ACTION_DELETE = 3,
|
||||
} eEditMesh_PreSelPreviewAction;
|
||||
|
||||
struct EditMesh_PreSelElem *EDBM_preselect_elem_create(void);
|
||||
void EDBM_preselect_elem_destroy(struct EditMesh_PreSelElem *psel);
|
||||
void EDBM_preselect_elem_clear(struct EditMesh_PreSelElem *psel);
|
||||
void EDBM_preselect_preview_clear(struct EditMesh_PreSelElem *psel);
|
||||
void EDBM_preselect_elem_draw(struct EditMesh_PreSelElem *psel, const float matrix[4][4]);
|
||||
void EDBM_preselect_elem_update_from_single(struct EditMesh_PreSelElem *psel,
|
||||
struct BMesh *bm,
|
||||
struct BMElem *ele,
|
||||
const float (*coords)[3]);
|
||||
|
||||
void EDBM_preselect_elem_update_preview(struct EditMesh_PreSelElem *psel,
|
||||
struct ViewContext *vc,
|
||||
struct BMesh *bm,
|
||||
struct BMElem *ele,
|
||||
const int mval[2]);
|
||||
void EDBM_preselect_action_set(struct EditMesh_PreSelElem *psel,
|
||||
eEditMesh_PreSelPreviewAction action);
|
||||
eEditMesh_PreSelPreviewAction EDBM_preselect_action_get(struct EditMesh_PreSelElem *psel);
|
||||
/* mesh_ops.c */
|
||||
void ED_operatortypes_mesh(void);
|
||||
void ED_operatormacros_mesh(void);
|
||||
|
||||
@@ -122,15 +122,151 @@ static bool edbm_preselect_or_active_init_viewcontext(bContext *C,
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int edbm_polybuild_transform_at_cursor_invoke(bContext *C,
|
||||
wmOperator *UNUSED(op),
|
||||
const wmEvent *UNUSED(event))
|
||||
{
|
||||
ViewContext vc;
|
||||
Base *basact = NULL;
|
||||
BMElem *ele_act = NULL;
|
||||
edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
|
||||
BMEditMesh *em = vc.em;
|
||||
BMesh *bm = em->bm;
|
||||
|
||||
invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
|
||||
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
|
||||
|
||||
edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX);
|
||||
|
||||
edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
|
||||
if (ele_act->head.htype == BM_VERT) {
|
||||
BM_vert_select_set(bm, (BMVert *)ele_act, true);
|
||||
}
|
||||
if (ele_act->head.htype == BM_EDGE) {
|
||||
BM_edge_select_set(bm, (BMEdge *)ele_act, true);
|
||||
}
|
||||
if (ele_act->head.htype == BM_FACE) {
|
||||
BM_face_select_set(bm, (BMFace *)ele_act, true);
|
||||
}
|
||||
|
||||
EDBM_mesh_normals_update(em);
|
||||
EDBM_update_generic(em, true, true);
|
||||
if (basact != NULL) {
|
||||
if (vc.view_layer->basact != basact) {
|
||||
ED_object_base_activate(C, basact);
|
||||
}
|
||||
}
|
||||
BM_select_history_store(bm, ele_act);
|
||||
WM_event_add_mousemove(C);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void MESH_OT_polybuild_transform_at_cursor(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Poly Build Transform at Cursor";
|
||||
ot->idname = "MESH_OT_polybuild_transform_at_cursor";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = edbm_polybuild_transform_at_cursor_invoke;
|
||||
ot->poll = EDBM_view3d_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* to give to transform */
|
||||
Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
|
||||
}
|
||||
|
||||
static int edbm_polybuild_delete_at_cursor_invoke(bContext *C,
|
||||
wmOperator *op,
|
||||
const wmEvent *UNUSED(event))
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
ViewContext vc;
|
||||
Base *basact = NULL;
|
||||
BMElem *ele_act = NULL;
|
||||
edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
|
||||
BMEditMesh *em = vc.em;
|
||||
BMesh *bm = em->bm;
|
||||
|
||||
invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
|
||||
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
|
||||
|
||||
edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX);
|
||||
|
||||
if (ele_act->head.htype == BM_FACE) {
|
||||
BMFace *f_act = (BMFace *)ele_act;
|
||||
EDBM_flag_disable_all(em, BM_ELEM_TAG);
|
||||
BM_elem_flag_enable(f_act, BM_ELEM_TAG);
|
||||
if (!EDBM_op_callf(em, op, "delete geom=%hf context=%i", BM_ELEM_TAG, DEL_FACES)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
if (ele_act->head.htype == BM_VERT) {
|
||||
BMVert *v_act = (BMVert *)ele_act;
|
||||
if (BM_vert_is_edge_pair(v_act)) {
|
||||
BM_edge_collapse(bm, v_act->e, v_act, true, true);
|
||||
changed = true;
|
||||
}
|
||||
else {
|
||||
EDBM_flag_disable_all(em, BM_ELEM_TAG);
|
||||
BM_elem_flag_enable(v_act, BM_ELEM_TAG);
|
||||
|
||||
if (!EDBM_op_callf(em,
|
||||
op,
|
||||
"dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
|
||||
BM_ELEM_TAG,
|
||||
false,
|
||||
false)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
EDBM_mesh_normals_update(em);
|
||||
EDBM_update_generic(em, true, true);
|
||||
if (basact != NULL) {
|
||||
if (vc.view_layer->basact != basact) {
|
||||
ED_object_base_activate(C, basact);
|
||||
}
|
||||
}
|
||||
WM_event_add_mousemove(C);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
else {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
}
|
||||
|
||||
void MESH_OT_polybuild_delete_at_cursor(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Poly Build Delete at Cursor";
|
||||
ot->idname = "MESH_OT_polybuild_delete_at_cursor";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = edbm_polybuild_delete_at_cursor_invoke;
|
||||
ot->poll = EDBM_view3d_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* to give to transform */
|
||||
Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Face at Cursor
|
||||
* \{ */
|
||||
|
||||
static int edbm_polybuild_face_at_cursor_invoke(bContext *C,
|
||||
wmOperator *UNUSED(op),
|
||||
const wmEvent *event)
|
||||
static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
float center[3];
|
||||
bool changed = false;
|
||||
@@ -168,20 +304,27 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C,
|
||||
mul_m4_v3(vc.obedit->obmat, center);
|
||||
ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center);
|
||||
mul_m4_v3(vc.obedit->imat, center);
|
||||
|
||||
BMVert *v_tri[3];
|
||||
v_tri[0] = e_act->v1;
|
||||
v_tri[1] = e_act->v2;
|
||||
v_tri[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
|
||||
if (e_act->l && e_act->l->v == v_tri[0]) {
|
||||
SWAP(BMVert *, v_tri[0], v_tri[1]);
|
||||
if (f_reference->len == 3 && RNA_boolean_get(op->ptr, "create_quads")) {
|
||||
const float fac = line_point_factor_v3(center, e_act->v1->co, e_act->v2->co);
|
||||
BMVert *v_new = BM_edge_split(bm, e_act, e_act->v1, NULL, CLAMPIS(fac, 0.0f, 1.0f));
|
||||
copy_v3_v3(v_new->co, center);
|
||||
edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
|
||||
BM_vert_select_set(bm, v_new, true);
|
||||
BM_select_history_store(bm, v_new);
|
||||
}
|
||||
else {
|
||||
BMVert *v_tri[3];
|
||||
v_tri[0] = e_act->v1;
|
||||
v_tri[1] = e_act->v2;
|
||||
v_tri[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
|
||||
if (e_act->l && e_act->l->v == v_tri[0]) {
|
||||
SWAP(BMVert *, v_tri[0], v_tri[1]);
|
||||
}
|
||||
BM_face_create_verts(bm, v_tri, 3, f_reference, BM_CREATE_NOP, true);
|
||||
edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
|
||||
BM_vert_select_set(bm, v_tri[2], true);
|
||||
BM_select_history_store(bm, v_tri[2]);
|
||||
}
|
||||
// BMFace *f_new =
|
||||
BM_face_create_verts(bm, v_tri, 3, f_reference, BM_CREATE_NOP, true);
|
||||
|
||||
edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
|
||||
BM_vert_select_set(bm, v_tri[2], true);
|
||||
BM_select_history_store(bm, v_tri[2]);
|
||||
changed = true;
|
||||
}
|
||||
else if (ele_act->head.htype == BM_VERT) {
|
||||
@@ -281,6 +424,11 @@ void MESH_OT_polybuild_face_at_cursor(wmOperatorType *ot)
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
RNA_def_boolean(ot->srna,
|
||||
"create_quads",
|
||||
true,
|
||||
"Create quads",
|
||||
"Automatically split edges in triangles to maintain quad topology");
|
||||
/* to give to transform */
|
||||
Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
|
||||
}
|
||||
|
||||
@@ -75,20 +75,49 @@ struct EditMesh_PreSelElem {
|
||||
|
||||
float (*verts)[3];
|
||||
int verts_len;
|
||||
|
||||
float (*preview_tris)[3][3];
|
||||
int preview_tris_len;
|
||||
float (*preview_lines)[2][3];
|
||||
int preview_lines_len;
|
||||
|
||||
eEditMesh_PreSelPreviewAction preview_action;
|
||||
};
|
||||
|
||||
void EDBM_preselect_action_set(struct EditMesh_PreSelElem *psel,
|
||||
eEditMesh_PreSelPreviewAction action)
|
||||
{
|
||||
psel->preview_action = action;
|
||||
}
|
||||
|
||||
eEditMesh_PreSelPreviewAction EDBM_preselect_action_get(struct EditMesh_PreSelElem *psel)
|
||||
{
|
||||
return psel->preview_action;
|
||||
}
|
||||
|
||||
struct EditMesh_PreSelElem *EDBM_preselect_elem_create(void)
|
||||
{
|
||||
struct EditMesh_PreSelElem *psel = MEM_callocN(sizeof(*psel), __func__);
|
||||
psel->preview_action = PRESELECT_ACTION_TRANSFORM;
|
||||
return psel;
|
||||
}
|
||||
|
||||
void EDBM_preselect_elem_destroy(struct EditMesh_PreSelElem *psel)
|
||||
{
|
||||
EDBM_preselect_elem_clear(psel);
|
||||
EDBM_preselect_preview_clear(psel);
|
||||
MEM_freeN(psel);
|
||||
}
|
||||
|
||||
void EDBM_preselect_preview_clear(struct EditMesh_PreSelElem *psel)
|
||||
{
|
||||
MEM_SAFE_FREE(psel->preview_tris);
|
||||
psel->preview_tris_len = 0;
|
||||
|
||||
MEM_SAFE_FREE(psel->preview_lines);
|
||||
psel->preview_lines_len = 0;
|
||||
}
|
||||
|
||||
void EDBM_preselect_elem_clear(struct EditMesh_PreSelElem *psel)
|
||||
{
|
||||
MEM_SAFE_FREE(psel->edges);
|
||||
@@ -112,9 +141,42 @@ void EDBM_preselect_elem_draw(struct EditMesh_PreSelElem *psel, const float matr
|
||||
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
immUniformColor3ub(255, 0, 255);
|
||||
|
||||
immUniformColor4ub(141, 171, 186, 100);
|
||||
if (psel->preview_action != PRESELECT_ACTION_TRANSFORM) {
|
||||
if (psel->preview_tris_len > 0) {
|
||||
immBegin(GPU_PRIM_TRIS, psel->preview_tris_len * 3);
|
||||
|
||||
for (int i = 0; i < psel->preview_tris_len; i++) {
|
||||
immVertex3fv(pos, psel->preview_tris[i][0]);
|
||||
immVertex3fv(pos, psel->preview_tris[i][1]);
|
||||
immVertex3fv(pos, psel->preview_tris[i][2]);
|
||||
}
|
||||
immEnd();
|
||||
}
|
||||
|
||||
if (psel->preview_lines_len > 0) {
|
||||
|
||||
immUniformColor4ub(3, 161, 252, 200);
|
||||
GPU_line_width(2.0f);
|
||||
immBegin(GPU_PRIM_LINES, psel->preview_lines_len * 2);
|
||||
for (int i = 0; i < psel->preview_lines_len; i++) {
|
||||
immVertex3fv(pos, psel->preview_lines[i][0]);
|
||||
immVertex3fv(pos, psel->preview_lines[i][1]);
|
||||
}
|
||||
immEnd();
|
||||
}
|
||||
}
|
||||
|
||||
if (psel->preview_action == PRESELECT_ACTION_DELETE) {
|
||||
immUniformColor4ub(252, 49, 10, 200);
|
||||
}
|
||||
else {
|
||||
immUniformColor4ub(3, 161, 252, 200);
|
||||
}
|
||||
|
||||
if (psel->edges_len > 0) {
|
||||
GPU_line_width(3.0f);
|
||||
immBegin(GPU_PRIM_LINES, psel->edges_len * 2);
|
||||
|
||||
for (int i = 0; i < psel->edges_len; i++) {
|
||||
@@ -126,7 +188,7 @@ void EDBM_preselect_elem_draw(struct EditMesh_PreSelElem *psel, const float matr
|
||||
}
|
||||
|
||||
if (psel->verts_len > 0) {
|
||||
GPU_point_size(3.0f);
|
||||
GPU_point_size(4.0f);
|
||||
|
||||
immBegin(GPU_PRIM_POINTS, psel->verts_len);
|
||||
|
||||
@@ -167,6 +229,122 @@ static void view3d_preselect_mesh_elem_update_from_edge(struct EditMesh_PreSelEl
|
||||
psel->edges_len = 1;
|
||||
}
|
||||
|
||||
static void view3d_preselect_update_preview_triangle_from_vert(struct EditMesh_PreSelElem *psel,
|
||||
ViewContext *vc,
|
||||
BMesh *UNUSED(bm),
|
||||
BMVert *eed,
|
||||
const int mval[2])
|
||||
{
|
||||
BMVert *v_act = eed;
|
||||
BMEdge *e_pair[2] = {NULL};
|
||||
float center[3];
|
||||
|
||||
if (v_act->e != NULL) {
|
||||
for (uint allow_wire = 0; allow_wire < 2 && (e_pair[1] == NULL); allow_wire++) {
|
||||
int i = 0;
|
||||
BMEdge *e_iter = v_act->e;
|
||||
do {
|
||||
if ((BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) &&
|
||||
(allow_wire ? BM_edge_is_wire(e_iter) : BM_edge_is_boundary(e_iter))) {
|
||||
if (i == 2) {
|
||||
e_pair[0] = e_pair[1] = NULL;
|
||||
break;
|
||||
}
|
||||
e_pair[i++] = e_iter;
|
||||
}
|
||||
} while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_act)) != v_act->e);
|
||||
}
|
||||
}
|
||||
|
||||
if (e_pair[1] != NULL) {
|
||||
mul_v3_m4v3(center, vc->obedit->obmat, v_act->co);
|
||||
ED_view3d_win_to_3d_int(vc->v3d, vc->ar, center, mval, center);
|
||||
mul_m4_v3(vc->obedit->imat, center);
|
||||
|
||||
psel->preview_tris = MEM_mallocN(sizeof(*psel->preview_tris) * 2, __func__);
|
||||
psel->preview_lines = MEM_mallocN(sizeof(*psel->preview_lines) * 4, __func__);
|
||||
|
||||
copy_v3_v3(psel->preview_tris[0][0], e_pair[0]->v1->co);
|
||||
copy_v3_v3(psel->preview_tris[0][1], e_pair[0]->v2->co);
|
||||
copy_v3_v3(psel->preview_tris[0][2], center);
|
||||
|
||||
copy_v3_v3(psel->preview_tris[1][0], e_pair[1]->v1->co);
|
||||
copy_v3_v3(psel->preview_tris[1][1], e_pair[1]->v2->co);
|
||||
copy_v3_v3(psel->preview_tris[1][2], center);
|
||||
|
||||
copy_v3_v3(psel->preview_lines[0][0], e_pair[0]->v1->co);
|
||||
copy_v3_v3(psel->preview_lines[0][1], e_pair[0]->v2->co);
|
||||
|
||||
copy_v3_v3(psel->preview_lines[1][0], e_pair[1]->v1->co);
|
||||
copy_v3_v3(psel->preview_lines[1][1], e_pair[1]->v2->co);
|
||||
|
||||
copy_v3_v3(psel->preview_lines[2][0], center);
|
||||
if (e_pair[0]->v1 == v_act) {
|
||||
copy_v3_v3(psel->preview_lines[2][1], e_pair[0]->v2->co);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(psel->preview_lines[2][1], e_pair[0]->v1->co);
|
||||
}
|
||||
|
||||
copy_v3_v3(psel->preview_lines[3][0], center);
|
||||
if (e_pair[1]->v1 == v_act) {
|
||||
copy_v3_v3(psel->preview_lines[3][1], e_pair[1]->v2->co);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(psel->preview_lines[3][1], e_pair[1]->v1->co);
|
||||
}
|
||||
psel->preview_tris_len = 2;
|
||||
psel->preview_lines_len = 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void view3d_preselect_update_preview_triangle_from_face(struct EditMesh_PreSelElem *psel,
|
||||
ViewContext *UNUSED(vc),
|
||||
BMesh *UNUSED(bm),
|
||||
BMFace *efa,
|
||||
const int UNUSED(mval[2]))
|
||||
{
|
||||
float(*preview_lines)[2][3] = MEM_mallocN(sizeof(*psel->edges) * efa->len, __func__);
|
||||
BMLoop *l_iter, *l_first;
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
|
||||
int i = 0;
|
||||
do {
|
||||
vcos_get_pair(&l_iter->e->v1, preview_lines[i++], NULL);
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
psel->preview_lines = preview_lines;
|
||||
psel->preview_lines_len = efa->len;
|
||||
}
|
||||
|
||||
static void view3d_preselect_update_preview_triangle_from_edge(struct EditMesh_PreSelElem *psel,
|
||||
ViewContext *vc,
|
||||
BMesh *UNUSED(bm),
|
||||
BMEdge *eed,
|
||||
const int mval[2])
|
||||
{
|
||||
float center[3];
|
||||
psel->preview_tris = MEM_mallocN(sizeof(*psel->preview_tris), __func__);
|
||||
psel->preview_lines = MEM_mallocN(sizeof(*psel->preview_lines) * 3, __func__);
|
||||
mid_v3_v3v3(center, eed->v1->co, eed->v2->co);
|
||||
mul_m4_v3(vc->obedit->obmat, center);
|
||||
ED_view3d_win_to_3d_int(vc->v3d, vc->ar, center, mval, center);
|
||||
mul_m4_v3(vc->obedit->imat, center);
|
||||
|
||||
copy_v3_v3(psel->preview_tris[0][0], eed->v1->co);
|
||||
copy_v3_v3(psel->preview_tris[0][1], eed->v2->co);
|
||||
copy_v3_v3(psel->preview_tris[0][2], center);
|
||||
|
||||
copy_v3_v3(psel->preview_lines[0][0], eed->v1->co);
|
||||
copy_v3_v3(psel->preview_lines[0][1], eed->v2->co);
|
||||
|
||||
copy_v3_v3(psel->preview_lines[1][0], eed->v2->co);
|
||||
copy_v3_v3(psel->preview_lines[1][1], center);
|
||||
|
||||
copy_v3_v3(psel->preview_lines[2][0], center);
|
||||
copy_v3_v3(psel->preview_lines[2][1], eed->v1->co);
|
||||
psel->preview_tris_len = 1;
|
||||
psel->preview_lines_len = 3;
|
||||
}
|
||||
|
||||
static void view3d_preselect_mesh_elem_update_from_face(struct EditMesh_PreSelElem *psel,
|
||||
BMesh *UNUSED(bm),
|
||||
BMFace *efa,
|
||||
@@ -209,4 +387,28 @@ void EDBM_preselect_elem_update_from_single(struct EditMesh_PreSelElem *psel,
|
||||
}
|
||||
}
|
||||
|
||||
void EDBM_preselect_elem_update_preview(struct EditMesh_PreSelElem *psel,
|
||||
struct ViewContext *vc,
|
||||
struct BMesh *bm,
|
||||
struct BMElem *ele,
|
||||
const int mval[2])
|
||||
{
|
||||
EDBM_preselect_preview_clear(psel);
|
||||
|
||||
switch (ele->head.htype) {
|
||||
case BM_VERT:
|
||||
if (EDBM_preselect_action_get(psel) == PRESELECT_ACTION_CREATE) {
|
||||
view3d_preselect_update_preview_triangle_from_vert(psel, vc, bm, (BMVert *)ele, mval);
|
||||
}
|
||||
break;
|
||||
case BM_EDGE:
|
||||
view3d_preselect_update_preview_triangle_from_edge(psel, vc, bm, (BMEdge *)ele, mval);
|
||||
break;
|
||||
case BM_FACE:
|
||||
view3d_preselect_update_preview_triangle_from_face(psel, vc, bm, (BMFace *)ele, mval);
|
||||
break;
|
||||
default:
|
||||
BLI_assert(0);
|
||||
}
|
||||
}
|
||||
/** \} */
|
||||
|
||||
@@ -1448,8 +1448,11 @@ bool EDBM_unified_findnearest(ViewContext *vc,
|
||||
bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
|
||||
Base **bases,
|
||||
const uint bases_len,
|
||||
bool use_boundary,
|
||||
int *r_base_index,
|
||||
bool use_boundary_vertices,
|
||||
bool use_boundary_edges,
|
||||
int *r_base_index_vert,
|
||||
int *r_base_index_edge,
|
||||
int *r_base_index_face,
|
||||
struct BMVert **r_eve,
|
||||
struct BMEdge **r_eed,
|
||||
struct BMFace **r_efa)
|
||||
@@ -1463,9 +1466,27 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
|
||||
BMElem *ele;
|
||||
} best = {0, NULL};
|
||||
|
||||
struct {
|
||||
uint base_index;
|
||||
BMElem *ele;
|
||||
} best_vert = {0, NULL};
|
||||
|
||||
struct {
|
||||
uint base_index;
|
||||
BMElem *ele;
|
||||
} best_edge = {0, NULL};
|
||||
|
||||
struct {
|
||||
uint base_index;
|
||||
BMElem *ele;
|
||||
} best_face = {0, NULL};
|
||||
|
||||
if (ED_view3d_win_to_ray_clipped(
|
||||
vc->depsgraph, vc->ar, vc->v3d, mval_fl, ray_origin, ray_direction, true)) {
|
||||
float dist_sq_best = FLT_MAX;
|
||||
float dist_sq_best_vert = FLT_MAX;
|
||||
float dist_sq_best_edge = FLT_MAX;
|
||||
float dist_sq_best_face = FLT_MAX;
|
||||
|
||||
const bool use_vert = (r_eve != NULL);
|
||||
const bool use_edge = (r_eed != NULL);
|
||||
@@ -1495,18 +1516,23 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
|
||||
BM_mesh_elem_index_ensure(bm, BM_VERT);
|
||||
}
|
||||
|
||||
if (use_boundary && (use_vert || use_edge)) {
|
||||
if ((use_boundary_vertices || use_boundary_edges) && (use_vert || use_edge)) {
|
||||
BMEdge *e;
|
||||
BMIter eiter;
|
||||
BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
|
||||
if ((BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) && (BM_edge_is_boundary(e))) {
|
||||
if (use_vert) {
|
||||
if (use_vert && use_boundary_vertices) {
|
||||
for (uint j = 0; j < 2; j++) {
|
||||
BMVert *v = *((&e->v1) + j);
|
||||
float point[3];
|
||||
mul_v3_m4v3(point, obedit->obmat, coords ? coords[BM_elem_index_get(v)] : v->co);
|
||||
const float dist_sq_test = dist_squared_to_ray_v3_normalized(
|
||||
ray_origin, ray_direction, point);
|
||||
if (dist_sq_test < dist_sq_best_vert) {
|
||||
dist_sq_best_vert = dist_sq_test;
|
||||
best_vert.base_index = base_index;
|
||||
best_vert.ele = (BMElem *)v;
|
||||
}
|
||||
if (dist_sq_test < dist_sq_best) {
|
||||
dist_sq_best = dist_sq_test;
|
||||
best.base_index = base_index;
|
||||
@@ -1515,7 +1541,7 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
|
||||
}
|
||||
}
|
||||
|
||||
if (use_edge) {
|
||||
if (use_edge && use_boundary_edges) {
|
||||
float point[3];
|
||||
#if 0
|
||||
const float dist_sq_test = dist_squared_ray_to_seg_v3(
|
||||
@@ -1531,6 +1557,11 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
|
||||
mul_m4_v3(obedit->obmat, point);
|
||||
const float dist_sq_test = dist_squared_to_ray_v3_normalized(
|
||||
ray_origin, ray_direction, point);
|
||||
if (dist_sq_test < dist_sq_best_edge) {
|
||||
dist_sq_best_edge = dist_sq_test;
|
||||
best_edge.base_index = base_index;
|
||||
best_edge.ele = (BMElem *)e;
|
||||
}
|
||||
if (dist_sq_test < dist_sq_best) {
|
||||
dist_sq_best = dist_sq_test;
|
||||
best.base_index = base_index;
|
||||
@@ -1541,46 +1572,55 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Non boundary case. */
|
||||
if (use_vert) {
|
||||
BMVert *v;
|
||||
BMIter viter;
|
||||
BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
|
||||
if (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == false) {
|
||||
float point[3];
|
||||
mul_v3_m4v3(point, obedit->obmat, v->co);
|
||||
const float dist_sq_test = dist_squared_to_ray_v3_normalized(
|
||||
ray_origin, ray_direction, v->co);
|
||||
if (dist_sq_test < dist_sq_best) {
|
||||
dist_sq_best = dist_sq_test;
|
||||
best.base_index = base_index;
|
||||
best.ele = (BMElem *)v;
|
||||
}
|
||||
/* Non boundary case. */
|
||||
if (use_vert && !use_boundary_vertices) {
|
||||
BMVert *v;
|
||||
BMIter viter;
|
||||
BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
|
||||
if (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == false) {
|
||||
float point[3];
|
||||
mul_v3_m4v3(point, obedit->obmat, coords ? coords[BM_elem_index_get(v)] : v->co);
|
||||
const float dist_sq_test = dist_squared_to_ray_v3_normalized(
|
||||
ray_origin, ray_direction, point);
|
||||
if (dist_sq_test < dist_sq_best_vert) {
|
||||
dist_sq_best_vert = dist_sq_test;
|
||||
best_vert.base_index = base_index;
|
||||
best_vert.ele = (BMElem *)v;
|
||||
}
|
||||
if (dist_sq_test < dist_sq_best) {
|
||||
dist_sq_best = dist_sq_test;
|
||||
best.base_index = base_index;
|
||||
best.ele = (BMElem *)v;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (use_edge) {
|
||||
BMEdge *e;
|
||||
BMIter eiter;
|
||||
BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
|
||||
if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) {
|
||||
float point[3];
|
||||
if (coords) {
|
||||
mid_v3_v3v3(
|
||||
point, coords[BM_elem_index_get(e->v1)], coords[BM_elem_index_get(e->v2)]);
|
||||
}
|
||||
else {
|
||||
mid_v3_v3v3(point, e->v1->co, e->v2->co);
|
||||
}
|
||||
mul_m4_v3(obedit->obmat, point);
|
||||
const float dist_sq_test = dist_squared_to_ray_v3_normalized(
|
||||
ray_origin, ray_direction, point);
|
||||
if (dist_sq_test < dist_sq_best) {
|
||||
dist_sq_best = dist_sq_test;
|
||||
best.base_index = base_index;
|
||||
best.ele = (BMElem *)e;
|
||||
}
|
||||
}
|
||||
|
||||
if (use_edge && !use_boundary_edges) {
|
||||
BMEdge *e;
|
||||
BMIter eiter;
|
||||
BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
|
||||
if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) {
|
||||
float point[3];
|
||||
if (coords) {
|
||||
mid_v3_v3v3(
|
||||
point, coords[BM_elem_index_get(e->v1)], coords[BM_elem_index_get(e->v2)]);
|
||||
}
|
||||
else {
|
||||
mid_v3_v3v3(point, e->v1->co, e->v2->co);
|
||||
}
|
||||
mul_m4_v3(obedit->obmat, point);
|
||||
const float dist_sq_test = dist_squared_to_ray_v3_normalized(
|
||||
ray_origin, ray_direction, point);
|
||||
if (dist_sq_test < dist_sq_best_edge) {
|
||||
dist_sq_best_edge = dist_sq_test;
|
||||
best_edge.base_index = base_index;
|
||||
best_edge.ele = (BMElem *)e;
|
||||
}
|
||||
if (dist_sq_test < dist_sq_best) {
|
||||
dist_sq_best = dist_sq_test;
|
||||
best.base_index = base_index;
|
||||
best.ele = (BMElem *)e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1601,6 +1641,11 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
|
||||
mul_m4_v3(obedit->obmat, point);
|
||||
const float dist_sq_test = dist_squared_to_ray_v3_normalized(
|
||||
ray_origin, ray_direction, point);
|
||||
if (dist_sq_test < dist_sq_best_face) {
|
||||
dist_sq_best_face = dist_sq_test;
|
||||
best_face.base_index = base_index;
|
||||
best_face.ele = (BMElem *)f;
|
||||
}
|
||||
if (dist_sq_test < dist_sq_best) {
|
||||
dist_sq_best = dist_sq_test;
|
||||
best.base_index = base_index;
|
||||
@@ -1612,7 +1657,10 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
|
||||
}
|
||||
}
|
||||
|
||||
*r_base_index = best.base_index;
|
||||
*r_base_index_vert = best_vert.base_index;
|
||||
*r_base_index_edge = best_edge.base_index;
|
||||
*r_base_index_face = best_face.base_index;
|
||||
|
||||
if (r_eve) {
|
||||
*r_eve = NULL;
|
||||
}
|
||||
@@ -1623,22 +1671,17 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
|
||||
*r_efa = NULL;
|
||||
}
|
||||
|
||||
if (best.ele) {
|
||||
switch (best.ele->head.htype) {
|
||||
case BM_VERT:
|
||||
*r_eve = (BMVert *)best.ele;
|
||||
break;
|
||||
case BM_EDGE:
|
||||
*r_eed = (BMEdge *)best.ele;
|
||||
break;
|
||||
case BM_FACE:
|
||||
*r_efa = (BMFace *)best.ele;
|
||||
break;
|
||||
default:
|
||||
BLI_assert(0);
|
||||
}
|
||||
if (best_vert.ele) {
|
||||
*r_eve = (BMVert *)best_vert.ele;
|
||||
}
|
||||
return (best.ele != NULL);
|
||||
if (best_edge.ele) {
|
||||
*r_eed = (BMEdge *)best_edge.ele;
|
||||
}
|
||||
if (best_face.ele) {
|
||||
*r_efa = (BMFace *)best_face.ele;
|
||||
}
|
||||
|
||||
return (best_vert.ele != NULL || best_edge.ele != NULL || best_face.ele != NULL);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -122,6 +122,8 @@ void MESH_GGT_spin_redo(struct wmGizmoGroupType *gzgt);
|
||||
void MESH_OT_polybuild_face_at_cursor(struct wmOperatorType *ot);
|
||||
void MESH_OT_polybuild_split_at_cursor(struct wmOperatorType *ot);
|
||||
void MESH_OT_polybuild_dissolve_at_cursor(struct wmOperatorType *ot);
|
||||
void MESH_OT_polybuild_transform_at_cursor(struct wmOperatorType *ot);
|
||||
void MESH_OT_polybuild_delete_at_cursor(struct wmOperatorType *ot);
|
||||
|
||||
/* *** editmesh_inset.c *** */
|
||||
void MESH_OT_inset(struct wmOperatorType *ot);
|
||||
|
||||
@@ -148,6 +148,8 @@ void ED_operatortypes_mesh(void)
|
||||
WM_operatortype_append(MESH_OT_polybuild_face_at_cursor);
|
||||
WM_operatortype_append(MESH_OT_polybuild_split_at_cursor);
|
||||
WM_operatortype_append(MESH_OT_polybuild_dissolve_at_cursor);
|
||||
WM_operatortype_append(MESH_OT_polybuild_transform_at_cursor);
|
||||
WM_operatortype_append(MESH_OT_polybuild_delete_at_cursor);
|
||||
|
||||
WM_operatortype_append(MESH_OT_uv_texture_add);
|
||||
WM_operatortype_append(MESH_OT_uv_texture_remove);
|
||||
@@ -334,6 +336,25 @@ void ED_operatormacros_mesh(void)
|
||||
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
|
||||
RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false);
|
||||
RNA_boolean_set(otmacro->ptr, "mirror", false);
|
||||
|
||||
ot = WM_operatortype_append_macro("MESH_OT_polybuild_transform_at_cursor_move",
|
||||
"Transform at Cursor Move",
|
||||
"",
|
||||
OPTYPE_UNDO | OPTYPE_REGISTER);
|
||||
WM_operatortype_macro_define(ot, "MESH_OT_polybuild_transform_at_cursor");
|
||||
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
|
||||
RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false);
|
||||
RNA_boolean_set(otmacro->ptr, "mirror", false);
|
||||
|
||||
ot = WM_operatortype_append_macro("MESH_OT_polybuild_extrude_at_cursor_move",
|
||||
"Extrude at Cursor Move",
|
||||
"",
|
||||
OPTYPE_UNDO | OPTYPE_REGISTER);
|
||||
WM_operatortype_macro_define(ot, "MESH_OT_polybuild_transform_at_cursor");
|
||||
otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_edges_indiv");
|
||||
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
|
||||
RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false);
|
||||
RNA_boolean_set(otmacro->ptr, "mirror", false);
|
||||
}
|
||||
|
||||
/* note mesh keymap also for other space? */
|
||||
|
||||
@@ -77,7 +77,20 @@ static void gizmo_preselect_elem_draw(const bContext *UNUSED(C), wmGizmo *gz)
|
||||
|
||||
static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int mval[2])
|
||||
{
|
||||
wmEvent *event = CTX_wm_window(C)->eventstate;
|
||||
MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz;
|
||||
|
||||
/* Hack: Switch action mode based on key input */
|
||||
const bool is_ctrl_pressed = WM_event_modifier_flag(event) & KM_CTRL;
|
||||
const bool is_shift_pressed = WM_event_modifier_flag(event) & KM_SHIFT;
|
||||
EDBM_preselect_action_set(gz_ele->psel, PRESELECT_ACTION_TRANSFORM);
|
||||
if (is_ctrl_pressed && !is_shift_pressed) {
|
||||
EDBM_preselect_action_set(gz_ele->psel, PRESELECT_ACTION_CREATE);
|
||||
}
|
||||
if (!is_ctrl_pressed && is_shift_pressed) {
|
||||
EDBM_preselect_action_set(gz_ele->psel, PRESELECT_ACTION_DELETE);
|
||||
}
|
||||
|
||||
struct {
|
||||
Object *ob;
|
||||
BMElem *ele;
|
||||
@@ -87,18 +100,6 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int
|
||||
.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);
|
||||
@@ -115,32 +116,66 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int
|
||||
|
||||
{
|
||||
/* TODO: support faces. */
|
||||
int base_index = -1;
|
||||
int base_index_vert = -1;
|
||||
int base_index_edge = -1;
|
||||
int base_index_face = -1;
|
||||
BMVert *eve_test;
|
||||
BMEdge *eed_test;
|
||||
BMFace *efa_test;
|
||||
|
||||
if (EDBM_unified_findnearest_from_raycast(&vc,
|
||||
gz_ele->bases,
|
||||
gz_ele->bases_len,
|
||||
false,
|
||||
true,
|
||||
&base_index,
|
||||
&base_index_vert,
|
||||
&base_index_edge,
|
||||
&base_index_face,
|
||||
&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;
|
||||
&efa_test)) {
|
||||
if (EDBM_preselect_action_get(gz_ele->psel) == PRESELECT_ACTION_DELETE) {
|
||||
/* Delete action */
|
||||
if (efa_test) {
|
||||
best.ele = (BMElem *)efa_test;
|
||||
best.base_index = base_index_face;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
BLI_assert(0);
|
||||
/* Transform and create action */
|
||||
if (eed_test) {
|
||||
best.ele = (BMElem *)eed_test;
|
||||
best.base_index = base_index_edge;
|
||||
}
|
||||
}
|
||||
best.base_index = base_index;
|
||||
|
||||
/* All actions use same vertex preselection */
|
||||
/* Retopology should always prioritize edge preselection. Only preselct a vertex when the
|
||||
* cursor is really close to it*/
|
||||
if (eve_test) {
|
||||
BMVert *vert = (BMVert *)eve_test;
|
||||
float vert_p_co[3], vert_co[3];
|
||||
float mval_f[2] = {UNPACK2(vc.mval)};
|
||||
mul_v3_m4v3(vert_co, gz_ele->bases[base_index_vert]->object->obmat, vert->co);
|
||||
ED_view3d_project(vc.ar, vert_co, vert_p_co);
|
||||
float len = len_v2v2(vert_p_co, mval_f);
|
||||
if (len < 35) {
|
||||
best.ele = (BMElem *)eve_test;
|
||||
best.base_index = base_index_vert;
|
||||
}
|
||||
if (!BM_vert_is_boundary(vert) &&
|
||||
EDBM_preselect_action_get(gz_ele->psel) != PRESELECT_ACTION_DELETE) {
|
||||
best.ele = (BMElem *)eve_test;
|
||||
best.base_index = base_index_vert;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check above should never fail, if it does it's an internal error. */
|
||||
BLI_assert(best.base_index != -1);
|
||||
|
||||
Base *base = gz_ele->bases[best.base_index];
|
||||
best.ob = base->object;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,32 +202,30 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int
|
||||
}
|
||||
}
|
||||
|
||||
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) */
|
||||
if (best.ele) {
|
||||
const float(*coords)[3] = NULL;
|
||||
{
|
||||
Object *ob = gz_ele->bases[gz_ele->base_index]->object;
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_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);
|
||||
EDBM_preselect_elem_update_preview(gz_ele->psel, &vc, bm, best.ele, mval);
|
||||
}
|
||||
else {
|
||||
if (best.ele) {
|
||||
const float(*coords)[3] = NULL;
|
||||
{
|
||||
Object *ob = gz_ele->bases[gz_ele->base_index]->object;
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_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);
|
||||
}
|
||||
EDBM_preselect_elem_clear(gz_ele->psel);
|
||||
EDBM_preselect_preview_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);
|
||||
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);
|
||||
|
||||
if (best.ele) {
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
ED_region_tag_redraw(ar);
|
||||
}
|
||||
@@ -471,5 +504,4 @@ void ED_view3d_gizmo_mesh_preselect_get_active(bContext *C,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
Reference in New Issue
Block a user