Transform: use a threshold for UV snapping
Unlike 3Dview snapping, UV snapping is always done to the UV closest to the mouse cursor, no matter the distance. From the user's point of view, this appears to be an inconsistency (See {T93538}). Therefore, set a minimum distance for snapping and, as in 3D View and highlight the snap with a drawing of a circle. Release Note: https://wiki.blender.org/wiki/Reference/Release_Notes/3.3/Modeling Reviewed By: #uv_editing, campbellbarton Maniphest Tasks: T93538 Differential Revision: https://developer.blender.org/D13873
This commit is contained in:
parent
08daeb9472
commit
d2271cf939
Notes:
blender-bot
2023-02-14 03:03:03 +01:00
Referenced by commit0c8de0eb3b
, Fix T100632: Regression: Node border snap guide line not drawing properly Referenced by commit046b45749c
, Fix cursor snap not acting on selected UVs Referenced by issue #100632, Regression: Node border snap guide line not drawing properly Referenced by issue #93538, UV Snapping behaviour inconsistency
|
@ -24,6 +24,7 @@ struct Object;
|
|||
struct Scene;
|
||||
struct SpaceImage;
|
||||
struct ToolSettings;
|
||||
struct View2D;
|
||||
struct ViewLayer;
|
||||
struct bContext;
|
||||
struct bNode;
|
||||
|
@ -242,15 +243,12 @@ void uvedit_deselect_flush(const struct Scene *scene, struct BMEditMesh *em);
|
|||
*/
|
||||
void uvedit_select_flush(const struct Scene *scene, struct BMEditMesh *em);
|
||||
|
||||
bool ED_uvedit_nearest_uv(const struct Scene *scene,
|
||||
struct Object *obedit,
|
||||
const float co[2],
|
||||
float *dist_sq,
|
||||
float r_uv[2]);
|
||||
bool ED_uvedit_nearest_uv_multi(const struct Scene *scene,
|
||||
bool ED_uvedit_nearest_uv_multi(const struct View2D *v2d,
|
||||
const struct Scene *scene,
|
||||
struct Object **objects,
|
||||
uint objects_len,
|
||||
const float co[2],
|
||||
const int mval[2],
|
||||
const bool ignore_selected,
|
||||
float *dist_sq,
|
||||
float r_uv[2]);
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "BLI_math.h"
|
||||
|
||||
#include "GPU_immediate.h"
|
||||
#include "GPU_matrix.h"
|
||||
#include "GPU_state.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
@ -25,6 +26,7 @@
|
|||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "ED_gizmo_library.h"
|
||||
|
@ -173,20 +175,20 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
|
|||
return;
|
||||
}
|
||||
|
||||
UI_GetThemeColor3ubv(TH_TRANSFORM, col);
|
||||
col[3] = 128;
|
||||
|
||||
UI_GetThemeColor3ubv(TH_SELECT, selectedCol);
|
||||
selectedCol[3] = 128;
|
||||
|
||||
UI_GetThemeColor3ubv(TH_ACTIVE, activeCol);
|
||||
activeCol[3] = 192;
|
||||
|
||||
if (t->spacetype == SPACE_VIEW3D) {
|
||||
bool draw_target = (t->tsnap.status & TARGET_INIT) &&
|
||||
(t->tsnap.mode & SCE_SNAP_MODE_EDGE_PERPENDICULAR);
|
||||
|
||||
if (draw_target || validSnap(t)) {
|
||||
UI_GetThemeColor3ubv(TH_TRANSFORM, col);
|
||||
col[3] = 128;
|
||||
|
||||
UI_GetThemeColor3ubv(TH_SELECT, selectedCol);
|
||||
selectedCol[3] = 128;
|
||||
|
||||
UI_GetThemeColor3ubv(TH_ACTIVE, activeCol);
|
||||
activeCol[3] = 192;
|
||||
|
||||
const float *loc_cur = NULL;
|
||||
const float *loc_prev = NULL;
|
||||
const float *normal = NULL;
|
||||
|
@ -240,8 +242,26 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
|
|||
}
|
||||
else if (t->spacetype == SPACE_IMAGE) {
|
||||
if (validSnap(t)) {
|
||||
/* This will not draw, and I'm nor sure why - campbell */
|
||||
/* TODO: see 2.7x for non-working code */
|
||||
uint pos = GPU_vertformat_attr_add(
|
||||
immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
|
||||
float x, y;
|
||||
const float snap_point[2] = {
|
||||
t->tsnap.snapPoint[0] / t->aspect[0],
|
||||
t->tsnap.snapPoint[1] / t->aspect[1],
|
||||
};
|
||||
UI_view2d_view_to_region_fl(&t->region->v2d, UNPACK2(snap_point), &x, &y);
|
||||
float radius = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize;
|
||||
|
||||
GPU_matrix_push_projection();
|
||||
wmOrtho2_region_pixelspace(t->region);
|
||||
|
||||
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
|
||||
immUniformColor3ub(255, 255, 255);
|
||||
imm_draw_circle_wire_2d(pos, x, y, radius, 8);
|
||||
immUnbindProgram();
|
||||
|
||||
GPU_matrix_pop_projection();
|
||||
}
|
||||
}
|
||||
else if (t->spacetype == SPACE_NODE) {
|
||||
|
@ -990,17 +1010,19 @@ static void snap_calc_uv_fn(TransInfo *t, float *UNUSED(vec))
|
|||
{
|
||||
BLI_assert(t->spacetype == SPACE_IMAGE);
|
||||
if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) {
|
||||
float co[2];
|
||||
|
||||
UI_view2d_region_to_view(&t->region->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
|
||||
|
||||
uint objects_len = 0;
|
||||
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
|
||||
t->view_layer, NULL, &objects_len);
|
||||
|
||||
float dist_sq = FLT_MAX;
|
||||
if (ED_uvedit_nearest_uv_multi(
|
||||
t->scene, objects, objects_len, co, &dist_sq, t->tsnap.snapPoint)) {
|
||||
float dist_sq = square_f((float)SNAP_MIN_DISTANCE);
|
||||
if (ED_uvedit_nearest_uv_multi(&t->region->v2d,
|
||||
t->scene,
|
||||
objects,
|
||||
objects_len,
|
||||
t->mval,
|
||||
true,
|
||||
&dist_sq,
|
||||
t->tsnap.snapPoint)) {
|
||||
t->tsnap.snapPoint[0] *= t->aspect[0];
|
||||
t->tsnap.snapPoint[1] *= t->aspect[1];
|
||||
|
||||
|
|
|
@ -1019,8 +1019,13 @@ bool uv_find_nearest_vert_multi(Scene *scene,
|
|||
return found;
|
||||
}
|
||||
|
||||
bool ED_uvedit_nearest_uv(
|
||||
const Scene *scene, Object *obedit, const float co[2], float *dist_sq, float r_uv[2])
|
||||
static bool uvedit_nearest_uv(const Scene *scene,
|
||||
Object *obedit,
|
||||
const float co[2],
|
||||
const float scale[2],
|
||||
const bool ignore_selected,
|
||||
float *dist_sq,
|
||||
float r_uv[2])
|
||||
{
|
||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||
BMIter iter;
|
||||
|
@ -1035,8 +1040,14 @@ bool ED_uvedit_nearest_uv(
|
|||
BMLoop *l_iter, *l_first;
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
|
||||
do {
|
||||
if (ignore_selected && uvedit_uv_select_test(scene, l_iter, cd_loop_uv_offset)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const float *uv = ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv;
|
||||
const float dist_test = len_squared_v2v2(co, uv);
|
||||
float co_tmp[2];
|
||||
mul_v2_v2v2(co_tmp, scale, uv);
|
||||
const float dist_test = len_squared_v2v2(co, co_tmp);
|
||||
if (dist_best > dist_test) {
|
||||
dist_best = dist_test;
|
||||
uv_best = uv;
|
||||
|
@ -1052,17 +1063,27 @@ bool ED_uvedit_nearest_uv(
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ED_uvedit_nearest_uv_multi(const Scene *scene,
|
||||
bool ED_uvedit_nearest_uv_multi(const View2D *v2d,
|
||||
const Scene *scene,
|
||||
Object **objects,
|
||||
const uint objects_len,
|
||||
const float co[2],
|
||||
const int mval[2],
|
||||
const bool ignore_selected,
|
||||
float *dist_sq,
|
||||
float r_uv[2])
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
float scale[2], offset[2];
|
||||
UI_view2d_scale_get(v2d, &scale[0], &scale[1]);
|
||||
UI_view2d_view_to_region_fl(v2d, 0.0f, 0.0f, &offset[0], &offset[1]);
|
||||
|
||||
float co[2];
|
||||
sub_v2_v2v2(co, (float[2]){UNPACK2(mval)}, offset);
|
||||
|
||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||
Object *obedit = objects[ob_index];
|
||||
if (ED_uvedit_nearest_uv(scene, obedit, co, dist_sq, r_uv)) {
|
||||
if (uvedit_nearest_uv(scene, obedit, co, scale, ignore_selected, dist_sq, r_uv)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue