WIP: Snapping & precision modeling improvements #105941
|
@ -80,4 +80,15 @@ def keyconfig_update(keyconfig_data, keyconfig_version):
|
|||
km_items.append(('ROTATE_NORMALS', {"type": 'N', "value": 'PRESS'}, None))
|
||||
break
|
||||
|
||||
if keyconfig_version <= (3, 6, 2):
|
||||
if not has_copy:
|
||||
keyconfig_data = copy.deepcopy(keyconfig_data)
|
||||
has_copy = True
|
||||
|
||||
# "Snap Source Toggle" did not exist until then.
|
||||
for km_name, _km_parms, km_items_data in keyconfig_data:
|
||||
if km_name == "Transform Modal Map":
|
||||
km_items_data["items"].append(("EDIT_SNAP_SOURCE", {"type": 'B', "value": 'PRESS'}, None))
|
||||
break
|
||||
|
||||
return keyconfig_data
|
||||
|
|
|
@ -346,7 +346,6 @@ url_manual_mapping = (
|
|||
("bpy.types.toolsettings.use_edge_path_live_unwrap*", "modeling/meshes/tools/tool_settings.html#bpy-types-toolsettings-use-edge-path-live-unwrap"),
|
||||
("bpy.types.toolsettings.use_gpencil_draw_additive*", "grease_pencil/modes/draw/introduction.html#bpy-types-toolsettings-use-gpencil-draw-additive"),
|
||||
("bpy.types.toolsettings.use_snap_backface_culling*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-backface-culling"),
|
||||
("bpy.types.toolsettings.use_snap_uv_grid_absolute*", "editors/uv/controls/snapping.html#bpy-types-toolsettings-use-snap-uv-grid-absolute"),
|
||||
("bpy.types.toolsettings.use_transform_data_origin*", "scene_layout/object/tools/tool_settings.html#bpy-types-toolsettings-use-transform-data-origin"),
|
||||
("bpy.types.view3doverlay.sculpt_mode_mask_opacity*", "sculpt_paint/sculpting/editing/mask.html#bpy-types-view3doverlay-sculpt-mode-mask-opacity"),
|
||||
("bpy.types.view3doverlay.viewer_attribute_opacity*", "modeling/geometry_nodes/output/viewer.html#bpy-types-view3doverlay-viewer-attribute-opacity"),
|
||||
|
@ -538,7 +537,6 @@ url_manual_mapping = (
|
|||
("bpy.types.spacespreadsheet.show_only_selected*", "editors/spreadsheet.html#bpy-types-spacespreadsheet-show-only-selected"),
|
||||
("bpy.types.spacespreadsheetrowfilter.operation*", "editors/spreadsheet.html#bpy-types-spacespreadsheetrowfilter-operation"),
|
||||
("bpy.types.spacespreadsheetrowfilter.threshold*", "editors/spreadsheet.html#bpy-types-spacespreadsheetrowfilter-threshold"),
|
||||
("bpy.types.toolsettings.use_snap_grid_absolute*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-grid-absolute"),
|
||||
("bpy.types.transformsequence.use_uniform_scale*", "video_editing/edit/montage/strips/effects/transform.html#bpy-types-transformsequence-use-uniform-scale"),
|
||||
("bpy.types.view3doverlay.show_face_orientation*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-show-face-orientation"),
|
||||
("bpy.types.view3doverlay.show_viewer_attribute*", "modeling/geometry_nodes/output/viewer.html#bpy-types-view3doverlay-show-viewer-attribute"),
|
||||
|
|
|
@ -5882,6 +5882,7 @@ def km_transform_modal_map(params):
|
|||
("TRACKBALL", {"type": 'R', "value": 'PRESS'}, None),
|
||||
("RESIZE", {"type": 'S', "value": 'PRESS'}, None),
|
||||
("ROTATE_NORMALS", {"type": 'N', "value": 'PRESS'}, None),
|
||||
("EDIT_SNAP_SOURCE", {"type": 'B', "value": 'PRESS'}, None),
|
||||
("SNAP_TOGGLE", {"type": 'TAB', "value": 'PRESS', "shift": True}, None),
|
||||
("SNAP_INV_ON", {"type": 'LEFT_CTRL', "value": 'PRESS', "any": True}, None),
|
||||
("SNAP_INV_OFF", {"type": 'LEFT_CTRL', "value": 'RELEASE', "any": True}, None),
|
||||
|
|
|
@ -4034,6 +4034,7 @@ def km_transform_modal_map(_params):
|
|||
("TRACKBALL", {"type": 'R', "value": 'PRESS'}, None),
|
||||
("RESIZE", {"type": 'S', "value": 'PRESS'}, None),
|
||||
("ROTATE_NORMALS", {"type": 'N', "value": 'PRESS'}, None),
|
||||
("EDIT_SNAP_SOURCE", {"type": 'B', "value": 'PRESS'}, None),
|
||||
("SNAP_TOGGLE", {"type": 'TAB', "value": 'PRESS', "shift": True}, None),
|
||||
("SNAP_INV_ON", {"type": 'LEFT_CTRL', "value": 'PRESS', "any": True}, None),
|
||||
("SNAP_INV_OFF", {"type": 'LEFT_CTRL', "value": 'RELEASE', "any": True}, None),
|
||||
|
|
|
@ -978,8 +978,6 @@ class IMAGE_PT_snapping(Panel):
|
|||
row.prop(tool_settings, "snap_target", expand=True)
|
||||
|
||||
col.separator()
|
||||
if 'INCREMENT' in tool_settings.snap_uv_element:
|
||||
col.prop(tool_settings, "use_snap_uv_grid_absolute")
|
||||
|
||||
col.label(text="Affect")
|
||||
row = col.row(align=True)
|
||||
|
|
|
@ -7029,8 +7029,6 @@ class VIEW3D_PT_snapping(Panel):
|
|||
col.prop(tool_settings, "snap_elements", expand=True)
|
||||
|
||||
col.separator()
|
||||
if 'INCREMENT' in snap_elements:
|
||||
col.prop(tool_settings, "use_snap_grid_absolute")
|
||||
|
||||
if snap_elements != {'INCREMENT'}:
|
||||
if snap_elements != {'FACE_NEAREST'}:
|
||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 2
|
||||
#define BLENDER_FILE_SUBVERSION 3
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and show a warning if the file
|
||||
|
|
|
@ -136,7 +136,7 @@ static bool v3d_cursor_snap_calc_incremental(
|
|||
return false;
|
||||
}
|
||||
|
||||
if (scene->toolsettings->snap_flag & SCE_SNAP_ABS_GRID) {
|
||||
if (scene->toolsettings->snap_mode & SCE_SNAP_MODE_GRID) {
|
||||
co_relative = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -219,7 +219,7 @@ static bool idp_snap_calc_incremental(
|
|||
return false;
|
||||
}
|
||||
|
||||
if (scene->toolsettings->snap_flag & SCE_SNAP_ABS_GRID) {
|
||||
if (scene->toolsettings->snap_mode & SCE_SNAP_MODE_GRID) {
|
||||
co_relative = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ set(SRC
|
|||
transform_mode_shear.c
|
||||
transform_mode_shrink_fatten.c
|
||||
transform_mode_skin_resize.c
|
||||
transform_mode_snapsource.c
|
||||
transform_mode_tilt.c
|
||||
transform_mode_timescale.c
|
||||
transform_mode_timeslide.c
|
||||
|
|
|
@ -542,6 +542,19 @@ static void viewRedrawPost(bContext *C, TransInfo *t)
|
|||
static bool transform_modal_item_poll(const wmOperator *op, int value)
|
||||
{
|
||||
const TransInfo *t = op->customdata;
|
||||
if (t->modifiers & MOD_EDIT_SNAP_SOURCE) {
|
||||
if (value == TFM_MODAL_EDIT_SNAP_SOURCE) {
|
||||
return true;
|
||||
}
|
||||
else if (!ELEM(value,
|
||||
TFM_MODAL_CANCEL,
|
||||
TFM_MODAL_CONFIRM,
|
||||
TFM_MODAL_ADD_SNAP,
|
||||
TFM_MODAL_REMOVE_SNAP)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch (value) {
|
||||
case TFM_MODAL_CANCEL: {
|
||||
/* TODO: Canceling with LMB is not possible when the operator is activated
|
||||
|
@ -669,6 +682,21 @@ static bool transform_modal_item_poll(const wmOperator *op, int value)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case TFM_MODAL_EDIT_SNAP_SOURCE: {
|
||||
if (t->spacetype != SPACE_VIEW3D) {
|
||||
return false;
|
||||
}
|
||||
if (!ELEM(t->mode,
|
||||
TFM_TRANSLATION,
|
||||
TFM_ROTATION,
|
||||
TFM_RESIZE,
|
||||
TFM_EDGE_SLIDE,
|
||||
TFM_VERT_SLIDE)) {
|
||||
/* More modes can be added over time if this feature proves useful for them. */
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -685,6 +713,7 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
|
|||
{TFM_MODAL_PLANE_Y, "PLANE_Y", 0, "Y Plane", ""},
|
||||
{TFM_MODAL_PLANE_Z, "PLANE_Z", 0, "Z Plane", ""},
|
||||
{TFM_MODAL_CONS_OFF, "CONS_OFF", 0, "Clear Constraints", ""},
|
||||
{TFM_MODAL_EDIT_SNAP_SOURCE, "EDIT_SNAP_SOURCE", 0, "Set Snap Base", ""},
|
||||
{TFM_MODAL_SNAP_INV_ON, "SNAP_INV_ON", 0, "Snap Invert", ""},
|
||||
{TFM_MODAL_SNAP_INV_OFF, "SNAP_INV_OFF", 0, "Snap Invert (Off)", ""},
|
||||
{TFM_MODAL_SNAP_TOGGLE, "SNAP_TOGGLE", 0, "Snap Toggle", ""},
|
||||
|
@ -954,12 +983,16 @@ int transformEvent(TransInfo *t, const wmEvent *event)
|
|||
else if (event->type == EVT_MODAL_MAP) {
|
||||
switch (event->val) {
|
||||
case TFM_MODAL_CANCEL:
|
||||
t->state = TRANS_CANCEL;
|
||||
handled = true;
|
||||
if (!(t->modifiers & MOD_EDIT_SNAP_SOURCE)) {
|
||||
t->state = TRANS_CANCEL;
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
case TFM_MODAL_CONFIRM:
|
||||
t->state = TRANS_CONFIRM;
|
||||
handled = true;
|
||||
if (!(t->modifiers & MOD_EDIT_SNAP_SOURCE)) {
|
||||
t->state = TRANS_CONFIRM;
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
case TFM_MODAL_TRANSLATE:
|
||||
case TFM_MODAL_ROTATE:
|
||||
|
@ -1244,6 +1277,12 @@ int transformEvent(TransInfo *t, const wmEvent *event)
|
|||
t->redraw |= TREDRAW_HARD;
|
||||
}
|
||||
break;
|
||||
case TFM_MODAL_EDIT_SNAP_SOURCE:
|
||||
if (event->prev_val == KM_PRESS) {
|
||||
transform_mode_snap_source_init(t);
|
||||
t->redraw |= TREDRAW_HARD;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1751,43 +1790,6 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
|
|||
}
|
||||
}
|
||||
|
||||
static void initSnapSpatial(TransInfo *t, float r_snap[3], float *r_snap_precision)
|
||||
{
|
||||
/* Default values. */
|
||||
r_snap[0] = r_snap[1] = 1.0f;
|
||||
r_snap[2] = 0.0f;
|
||||
*r_snap_precision = 0.1f;
|
||||
|
||||
if (t->spacetype == SPACE_VIEW3D) {
|
||||
if (t->region->regiondata) {
|
||||
View3D *v3d = t->area->spacedata.first;
|
||||
r_snap[0] = r_snap[1] = r_snap[2] = ED_view3d_grid_view_scale(
|
||||
t->scene, v3d, t->region, NULL);
|
||||
}
|
||||
}
|
||||
else if (t->spacetype == SPACE_IMAGE) {
|
||||
SpaceImage *sima = t->area->spacedata.first;
|
||||
View2D *v2d = &t->region->v2d;
|
||||
int grid_size = SI_GRID_STEPS_LEN;
|
||||
float zoom_factor = ED_space_image_zoom_level(v2d, grid_size);
|
||||
float grid_steps_x[SI_GRID_STEPS_LEN];
|
||||
float grid_steps_y[SI_GRID_STEPS_LEN];
|
||||
|
||||
ED_space_image_grid_steps(sima, grid_steps_x, grid_steps_y, grid_size);
|
||||
/* Snapping value based on what type of grid is used (adaptive-subdividing or custom-grid). */
|
||||
r_snap[0] = ED_space_image_increment_snap_value(grid_size, grid_steps_x, zoom_factor);
|
||||
r_snap[1] = ED_space_image_increment_snap_value(grid_size, grid_steps_y, zoom_factor);
|
||||
*r_snap_precision = 0.5f;
|
||||
}
|
||||
else if (t->spacetype == SPACE_CLIP) {
|
||||
r_snap[0] = r_snap[1] = 0.125f;
|
||||
*r_snap_precision = 0.5f;
|
||||
}
|
||||
else if (t->spacetype == SPACE_NODE) {
|
||||
r_snap[0] = r_snap[1] = ED_node_grid_size();
|
||||
}
|
||||
}
|
||||
|
||||
bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event, int mode)
|
||||
{
|
||||
int options = 0;
|
||||
|
@ -1952,7 +1954,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
|
|||
|
||||
initSnapping(t, op); /* Initialize snapping data AFTER mode flags */
|
||||
|
||||
initSnapSpatial(t, t->snap_spatial, &t->snap_spatial_precision);
|
||||
transform_snap_grid_init(t);
|
||||
|
||||
/* EVIL! posemode code can switch translation to rotate when 1 bone is selected.
|
||||
* will be removed (ton) */
|
||||
|
|
|
@ -157,6 +157,7 @@ typedef enum {
|
|||
MOD_CONSTRAINT_SELECT_PLANE = 1 << 4,
|
||||
MOD_NODE_ATTACH = 1 << 5,
|
||||
MOD_SNAP_FORCED = 1 << 6,
|
||||
MOD_EDIT_SNAP_SOURCE = 1 << 7,
|
||||
} eTModifier;
|
||||
ENUM_OPERATORS(eTModifier, MOD_NODE_ATTACH)
|
||||
|
||||
|
@ -164,10 +165,8 @@ ENUM_OPERATORS(eTModifier, MOD_NODE_ATTACH)
|
|||
typedef enum eTSnap {
|
||||
SNAP_RESETTED = 0,
|
||||
SNAP_SOURCE_FOUND = 1 << 0,
|
||||
/* Special flag for snap to grid. */
|
||||
SNAP_TARGET_GRID_FOUND = 1 << 1,
|
||||
SNAP_TARGET_FOUND = 1 << 2,
|
||||
SNAP_MULTI_POINTS = 1 << 3,
|
||||
SNAP_TARGET_FOUND = 1 << 1,
|
||||
SNAP_MULTI_POINTS = 1 << 2,
|
||||
} eTSnap;
|
||||
ENUM_OPERATORS(eTSnap, SNAP_MULTI_POINTS)
|
||||
|
||||
|
@ -270,6 +269,8 @@ enum {
|
|||
TFM_MODAL_VERT_EDGE_SLIDE = 31,
|
||||
TFM_MODAL_TRACKBALL = 32,
|
||||
TFM_MODAL_ROTATE_NORMALS = 33,
|
||||
|
||||
TFM_MODAL_EDIT_SNAP_SOURCE = 34,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
@ -300,7 +301,6 @@ typedef struct TransSnap {
|
|||
float snap_source[3];
|
||||
/** to this point (in global-space). */
|
||||
float snap_target[3];
|
||||
float snap_target_grid[3];
|
||||
float snapNormal[3];
|
||||
char snapNodeBorder;
|
||||
ListBase points;
|
||||
|
@ -768,6 +768,7 @@ void applyMouseInput(struct TransInfo *t,
|
|||
const int mval[2],
|
||||
float output[3]);
|
||||
void transform_input_update(TransInfo *t, const float fac);
|
||||
void transform_input_reset(TransInfo *t, const int mval[2]);
|
||||
|
||||
void setCustomPoints(TransInfo *t, MouseInput *mi, const int start[2], const int end[2]);
|
||||
void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[2]);
|
||||
|
|
|
@ -101,6 +101,20 @@ static void constraint_plane_calc(const TransInfo *t, float r_plane[4])
|
|||
r_plane[3] = -dot_v3v3(r_plane, t->center_global);
|
||||
}
|
||||
|
||||
static void constraint_axis_calc(const TransInfo *t, float r_dir[4])
|
||||
{
|
||||
if (t->con.mode & CON_AXIS0) {
|
||||
copy_v3_v3(r_dir, t->spacemtx[0]);
|
||||
}
|
||||
else if (t->con.mode & CON_AXIS1) {
|
||||
copy_v3_v3(r_dir, t->spacemtx[1]);
|
||||
}
|
||||
else {
|
||||
BLI_assert(t->con.mode & CON_AXIS2);
|
||||
copy_v3_v3(r_dir, t->spacemtx[2]);
|
||||
}
|
||||
}
|
||||
|
||||
void constraintNumInput(TransInfo *t, float vec[3])
|
||||
{
|
||||
int mode = t->con.mode;
|
||||
|
@ -170,6 +184,20 @@ static void viewAxisCorrectCenter(const TransInfo *t, float t_con_center[3])
|
|||
}
|
||||
}
|
||||
|
||||
static bool isAxisProjectionViewAligned(const TransInfo *t, const float axis[3])
|
||||
{
|
||||
float angle = fabsf(angle_v3v3(axis, t->viewinv[2]));
|
||||
if (angle > (float)M_PI_2) {
|
||||
angle = (float)M_PI - angle;
|
||||
}
|
||||
|
||||
if (angle < DEG2RADF(5.0f)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Axis calculation taking the view into account, correcting view-aligned axis.
|
||||
*/
|
||||
|
@ -178,7 +206,7 @@ static void axisProjection(const TransInfo *t,
|
|||
const float in[3],
|
||||
float out[3])
|
||||
{
|
||||
float vec[3], factor, angle;
|
||||
float vec[3], factor;
|
||||
float t_con_center[3];
|
||||
|
||||
if (is_zero_v3(in)) {
|
||||
|
@ -190,15 +218,10 @@ static void axisProjection(const TransInfo *t,
|
|||
/* checks for center being too close to the view center */
|
||||
viewAxisCorrectCenter(t, t_con_center);
|
||||
|
||||
angle = fabsf(angle_v3v3(axis, t->viewinv[2]));
|
||||
if (angle > (float)M_PI_2) {
|
||||
angle = (float)M_PI - angle;
|
||||
}
|
||||
|
||||
/* For when view is parallel to constraint... will cause NaNs otherwise
|
||||
* So we take vertical motion in 3D space and apply it to the
|
||||
* constraint axis. Nice for camera grab + MMB */
|
||||
if (angle < DEG2RADF(5.0f)) {
|
||||
if (isAxisProjectionViewAligned(t, axis)) {
|
||||
project_v3_v3v3(vec, in, t->viewinv[1]);
|
||||
factor = dot_v3v3(t->viewinv[1], vec) * 2.0f;
|
||||
/* Since camera distance is quite relative, use quadratic relationship.
|
||||
|
@ -434,17 +457,7 @@ static void applyAxisConstraintVec(const TransInfo *t,
|
|||
}
|
||||
else if (dims == 1) {
|
||||
float c[3];
|
||||
|
||||
if (t->con.mode & CON_AXIS0) {
|
||||
copy_v3_v3(c, t->spacemtx[0]);
|
||||
}
|
||||
else if (t->con.mode & CON_AXIS1) {
|
||||
copy_v3_v3(c, t->spacemtx[1]);
|
||||
}
|
||||
else {
|
||||
BLI_assert(t->con.mode & CON_AXIS2);
|
||||
copy_v3_v3(c, t->spacemtx[2]);
|
||||
}
|
||||
constraint_axis_calc(t, c);
|
||||
|
||||
if (is_snap_to_edge) {
|
||||
transform_constraint_snap_axis_to_edge(t, c, out);
|
||||
|
@ -1250,3 +1263,34 @@ int getConstraintSpaceDimension(const TransInfo *t)
|
|||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
bool transform_constraint_isect_ray(const TransInfo *t,
|
||||
const float ray_co[3],
|
||||
const float ray_dir[3],
|
||||
float out[3])
|
||||
{
|
||||
float lambda;
|
||||
const int dims = getConstraintSpaceDimension(t);
|
||||
if (dims == 2) {
|
||||
float plane[4];
|
||||
constraint_plane_calc(t, plane);
|
||||
if (!isPlaneProjectionViewAligned(t, plane)) {
|
||||
if (isect_ray_plane_v3(ray_co, ray_dir, plane, &lambda, false)) {
|
||||
madd_v3_v3v3fl(out, ray_co, ray_dir, lambda);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (dims == 1) {
|
||||
float axis[3];
|
||||
constraint_axis_calc(t, axis);
|
||||
if (!isAxisProjectionViewAligned(t, axis)) {
|
||||
if (isect_ray_ray_v3(t->center_global, axis, ray_co, ray_dir, &lambda, NULL)) {
|
||||
madd_v3_v3v3fl(out, t->center_global, axis, lambda);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct TransInfo;
|
||||
|
||||
void constraintNumInput(TransInfo *t, float vec[3]);
|
||||
|
@ -57,3 +61,12 @@ bool isLockConstraint(const TransInfo *t);
|
|||
* (Which could happen for weird constraints not yet designed. Along a path for example.)
|
||||
*/
|
||||
int getConstraintSpaceDimension(const TransInfo *t);
|
||||
|
||||
bool transform_constraint_isect_ray(const TransInfo *t,
|
||||
const float ray_co[3],
|
||||
const float ray_dir[3],
|
||||
float out[3]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1229,6 +1229,7 @@ void tranformViewUpdate(TransInfo *t)
|
|||
|
||||
calculateCenter2D(t);
|
||||
transform_input_update(t, zoom_prev / zoom_new);
|
||||
transform_snap_grid_init(t);
|
||||
}
|
||||
|
||||
void calculatePropRatio(TransInfo *t)
|
||||
|
|
|
@ -494,4 +494,16 @@ void transform_input_update(TransInfo *t, const float fac)
|
|||
}
|
||||
}
|
||||
|
||||
void transform_input_reset(TransInfo *t, const int mval[2])
|
||||
{
|
||||
MouseInput *mi = &t->mouse;
|
||||
copy_v2_v2_int(mi->imval, mval);
|
||||
if (ELEM(mi->apply, InputAngle, InputAngleSpring)) {
|
||||
struct InputAngle_Data *data = mi->data;
|
||||
data->mval_prev[0] = mi->imval[0];
|
||||
data->mval_prev[1] = mi->imval[1];
|
||||
data->angle = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -155,6 +155,10 @@ void initShrinkFatten(TransInfo *t);
|
|||
|
||||
void initSkinResize(TransInfo *t);
|
||||
|
||||
/* transform_mode_snapsource.c */
|
||||
|
||||
void transform_mode_snap_source_init(TransInfo *t);
|
||||
|
||||
/* transform_mode_tilt.c */
|
||||
|
||||
void initTilt(TransInfo *t);
|
||||
|
|
|
@ -1483,6 +1483,41 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
|
|||
ED_area_status_text(t->area, str);
|
||||
}
|
||||
|
||||
static void edge_slide_transform_matrix_fn(struct TransInfo *t, float mat_xform[4][4])
|
||||
{
|
||||
float delta[3], orig_co[3], final_co[3];
|
||||
|
||||
EdgeSlideParams *slp = t->custom.mode.data;
|
||||
TransDataContainer *tc = edge_slide_container_first_ok(t);
|
||||
EdgeSlideData *sld_active = tc->custom.mode.data;
|
||||
TransDataEdgeSlideVert *sv_active = &sld_active->sv[sld_active->curr_sv_index];
|
||||
|
||||
copy_v3_v3(orig_co, sv_active->v_co_orig);
|
||||
|
||||
const float fac = t->values_final[0];
|
||||
float curr_length_fac = 0.0f;
|
||||
if (slp->use_even) {
|
||||
curr_length_fac = sv_active->edge_len * (((slp->flipped ? fac : -fac) + 1.0f) / 2.0f);
|
||||
}
|
||||
|
||||
edge_slide_apply_elem(sv_active,
|
||||
fac,
|
||||
curr_length_fac,
|
||||
slp->curr_side_unclamp,
|
||||
!(t->flag & T_ALT_TRANSFORM),
|
||||
slp->use_even,
|
||||
slp->flipped,
|
||||
final_co);
|
||||
|
||||
if (tc->use_local_mat) {
|
||||
mul_m4_v3(tc->mat, orig_co);
|
||||
mul_m4_v3(tc->mat, final_co);
|
||||
}
|
||||
|
||||
sub_v3_v3v3(delta, final_co, orig_co);
|
||||
add_v3_v3(mat_xform[3], delta);
|
||||
}
|
||||
|
||||
void initEdgeSlide_ex(
|
||||
TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp)
|
||||
{
|
||||
|
@ -1492,7 +1527,7 @@ void initEdgeSlide_ex(
|
|||
t->mode = TFM_EDGE_SLIDE;
|
||||
t->transform = applyEdgeSlide;
|
||||
t->handleEvent = handleEventEdgeSlide;
|
||||
t->transform_matrix = NULL;
|
||||
t->transform_matrix = edge_slide_transform_matrix_fn;
|
||||
t->tsnap.snap_mode_apply_fn = edge_slide_snap_apply;
|
||||
t->tsnap.snap_mode_distance_fn = transform_snap_distance_len_squared_fn;
|
||||
|
||||
|
|
|
@ -281,11 +281,19 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2]))
|
|||
ED_area_status_text(t->area, str);
|
||||
}
|
||||
|
||||
static void resize_transform_matrix_fn(struct TransInfo *t, float mat_xform[4][4])
|
||||
{
|
||||
float mat4[4][4];
|
||||
copy_m4_m3(mat4, t->mat);
|
||||
transform_pivot_set_m4(mat4, t->center_global);
|
||||
mul_m4_m4m4(mat_xform, mat4, mat_xform);
|
||||
}
|
||||
|
||||
void initResize(TransInfo *t, float mouse_dir_constraint[3])
|
||||
{
|
||||
t->mode = TFM_RESIZE;
|
||||
t->transform = applyResize;
|
||||
t->transform_matrix = NULL;
|
||||
t->transform_matrix = resize_transform_matrix_fn;
|
||||
t->tsnap.snap_mode_apply_fn = ApplySnapResize;
|
||||
t->tsnap.snap_mode_distance_fn = ResizeBetween;
|
||||
|
||||
|
|
|
@ -0,0 +1,247 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2001-2002 NaN Holding BV. All rights reserved. */
|
||||
|
||||
/** \file
|
||||
* \ingroup edtransform
|
||||
*/
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "DNA_windowmanager_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
#include "ED_transform_snap_object_context.h"
|
||||
|
||||
#include "transform.h"
|
||||
#include "transform_convert.h"
|
||||
#include "transform_gizmo.h"
|
||||
#include "transform_snap.h"
|
||||
|
||||
#include "transform_mode.h"
|
||||
|
||||
#define RESET_TRANSFORMATION
|
||||
#define REMOVE_GIZMO
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Transform Element
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* \note Small arrays / data-structures should be stored copied for faster memory access.
|
||||
*/
|
||||
struct SnapSouceCustomData {
|
||||
void (*transform_prev)(struct TransInfo *, const int[2]);
|
||||
eRedrawFlag (*handleEvent_prev)(struct TransInfo *, const struct wmEvent *);
|
||||
void *customdata_mode_prev;
|
||||
|
||||
eSnapTargetOP target_operation_prev;
|
||||
|
||||
struct {
|
||||
void (*apply)(struct TransInfo *t,
|
||||
struct MouseInput *mi,
|
||||
const double mval[2],
|
||||
float output[3]);
|
||||
void (*post)(struct TransInfo *t, float values[3]);
|
||||
bool use_virtual_mval;
|
||||
} mouse_prev;
|
||||
};
|
||||
|
||||
static void snapsource_end(TransInfo *t)
|
||||
{
|
||||
t->modifiers &= ~MOD_EDIT_SNAP_SOURCE;
|
||||
|
||||
/* Restore. */
|
||||
struct SnapSouceCustomData *customdata = t->custom.mode.data;
|
||||
t->transform = customdata->transform_prev;
|
||||
t->custom.mode.data = customdata->customdata_mode_prev;
|
||||
t->handleEvent = customdata->handleEvent_prev;
|
||||
|
||||
t->tsnap.target_operation = customdata->target_operation_prev;
|
||||
|
||||
t->mouse.apply = customdata->mouse_prev.apply;
|
||||
t->mouse.post = customdata->mouse_prev.post;
|
||||
t->mouse.use_virtual_mval = customdata->mouse_prev.use_virtual_mval;
|
||||
|
||||
transform_gizmo_3d_model_from_constraint_and_mode_set(t);
|
||||
|
||||
MEM_freeN(customdata);
|
||||
|
||||
t->tsnap.snap_source_fn = NULL;
|
||||
|
||||
tranform_snap_source_restore_context(t);
|
||||
}
|
||||
|
||||
static void snapsource_confirm(TransInfo *t)
|
||||
{
|
||||
BLI_assert(t->modifiers & MOD_EDIT_SNAP_SOURCE);
|
||||
getSnapPoint(t, t->tsnap.snap_source);
|
||||
|
||||
int mval[2];
|
||||
#ifndef RESET_TRANSFORMATION
|
||||
if (true) {
|
||||
if (t->transform_matrix) {
|
||||
float mat_inv[4][4];
|
||||
unit_m4(mat_inv);
|
||||
t->transform_matrix(t, mat_inv);
|
||||
invert_m4(mat_inv);
|
||||
mul_m4_v3(mat_inv, t->tsnap.snap_source);
|
||||
}
|
||||
else {
|
||||
float mat_inv[3][3];
|
||||
invert_m3_m3(mat_inv, t->mat);
|
||||
|
||||
mul_m3_v3(mat_inv, t->tsnap.snap_source);
|
||||
sub_v3_v3(t->tsnap.snap_source, t->vec);
|
||||
}
|
||||
|
||||
projectIntView(t, t->tsnap.snap_source, mval);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
copy_v2_v2_int(mval, t->mval);
|
||||
}
|
||||
|
||||
snapsource_end(t);
|
||||
transform_input_reset(t, mval);
|
||||
|
||||
/* Remote individual snap projection since this mode does not use the new `snap_source`. */
|
||||
t->tsnap.flag &= ~SCE_SNAP_PROJECT;
|
||||
}
|
||||
|
||||
static eRedrawFlag snapsource_handle_event_fn(struct TransInfo *t, const struct wmEvent *event)
|
||||
{
|
||||
if (event->type == EVT_MODAL_MAP) {
|
||||
switch (event->val) {
|
||||
case TFM_MODAL_CONFIRM:
|
||||
case TFM_MODAL_EDIT_SNAP_SOURCE:
|
||||
if (t->modifiers & MOD_EDIT_SNAP_SOURCE) {
|
||||
snapsource_confirm(t);
|
||||
|
||||
BLI_assert(t->state != TRANS_CONFIRM);
|
||||
}
|
||||
else {
|
||||
t->modifiers |= MOD_EDIT_SNAP_SOURCE;
|
||||
}
|
||||
break;
|
||||
case TFM_MODAL_CANCEL:
|
||||
snapsource_end(t);
|
||||
t->state = TRANS_CANCEL;
|
||||
return TREDRAW_SOFT;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (event->val == KM_RELEASE && t->state == TRANS_CONFIRM) {
|
||||
if (t->flag & T_RELEASE_CONFIRM && t->modifiers & MOD_EDIT_SNAP_SOURCE) {
|
||||
snapsource_confirm(t);
|
||||
t->flag &= ~T_RELEASE_CONFIRM;
|
||||
t->state = TRANS_RUNNING;
|
||||
}
|
||||
}
|
||||
return TREDRAW_NOTHING;
|
||||
}
|
||||
|
||||
static void snapsource_transform_fn(TransInfo *t, const int UNUSED(mval[2]))
|
||||
{
|
||||
BLI_assert(t->modifiers & MOD_EDIT_SNAP_SOURCE);
|
||||
|
||||
t->tsnap.snap_target_fn(t, NULL);
|
||||
t->redraw |= TREDRAW_SOFT;
|
||||
}
|
||||
|
||||
void transform_mode_snap_source_init(TransInfo *t)
|
||||
{
|
||||
if (t->transform == snapsource_transform_fn) {
|
||||
/* Already running. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (ELEM(t->mode, TFM_INIT, TFM_DUMMY)) {
|
||||
/* Fallback */
|
||||
transform_mode_init(t, NULL, TFM_TRANSLATION);
|
||||
}
|
||||
|
||||
struct SnapSouceCustomData *customdata = MEM_callocN(sizeof(*customdata), __func__);
|
||||
customdata->transform_prev = t->transform;
|
||||
customdata->customdata_mode_prev = t->custom.mode.data;
|
||||
customdata->handleEvent_prev = t->handleEvent;
|
||||
|
||||
customdata->target_operation_prev = t->tsnap.target_operation;
|
||||
|
||||
customdata->mouse_prev.apply = t->mouse.apply;
|
||||
customdata->mouse_prev.post = t->mouse.post;
|
||||
customdata->mouse_prev.use_virtual_mval = t->mouse.use_virtual_mval;
|
||||
|
||||
t->custom.mode.data = customdata;
|
||||
// t->custom.mode.use_free = true;
|
||||
|
||||
t->transform = snapsource_transform_fn;
|
||||
t->handleEvent = snapsource_handle_event_fn;
|
||||
|
||||
if (!(t->modifiers & MOD_SNAP) || !transformModeUseSnap(t)) {
|
||||
t->modifiers |= (MOD_SNAP | MOD_SNAP_FORCED);
|
||||
}
|
||||
|
||||
t->tsnap.target_operation = SCE_SNAP_TARGET_ALL;
|
||||
|
||||
if ((t->tsnap.status & SNAP_SOURCE_FOUND) == 0) {
|
||||
if (t->tsnap.snap_source_fn) {
|
||||
/* Calculate the current snap source for perpendicular snap. */
|
||||
t->tsnap.snap_source_fn(t);
|
||||
}
|
||||
if ((t->tsnap.status & SNAP_SOURCE_FOUND) == 0) {
|
||||
/* Fallback. */
|
||||
copy_v3_v3(t->tsnap.snap_source, t->center_global);
|
||||
t->tsnap.status |= SNAP_SOURCE_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
if (t->tsnap.mode == SCE_SNAP_MODE_INCREMENT) {
|
||||
/* Initialize snap modes for geometry. */
|
||||
t->tsnap.mode &= ~SCE_SNAP_MODE_INCREMENT;
|
||||
t->tsnap.mode |= SCE_SNAP_MODE_GEOM | SCE_SNAP_MODE_GRID & ~SCE_SNAP_MODE_FACE_NEAREST;
|
||||
}
|
||||
|
||||
if (t->data_type == &TransConvertType_Mesh) {
|
||||
ED_transform_snap_object_context_set_editmesh_callbacks(
|
||||
t->tsnap.object_context, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
#ifdef RESET_TRANSFORMATION
|
||||
/* Temporarily disable snapping.
|
||||
* We don't want #SCE_SNAP_PROJECT to affect `recalcData` for example. */
|
||||
t->tsnap.flag &= ~SCE_SNAP;
|
||||
|
||||
restoreTransObjects(t);
|
||||
|
||||
/* Restore snapping status. */
|
||||
transform_snap_flag_from_modifiers_set(t);
|
||||
|
||||
/* Reset initial values to restore gizmo position. */
|
||||
applyMouseInput(t, &t->mouse, t->mouse.imval, t->values_final);
|
||||
#endif
|
||||
|
||||
#ifdef REMOVE_GIZMO
|
||||
struct wmGizmo *gz = WM_gizmomap_get_modal(t->region->gizmo_map);
|
||||
if (gz) {
|
||||
const struct wmEvent *event = CTX_wm_window(t->context)->eventstate;
|
||||
# ifdef RESET_TRANSFORMATION
|
||||
wmGizmoFnModal modal_fn = gz->custom_modal ? gz->custom_modal : gz->type->modal;
|
||||
modal_fn(t->context, gz, event, 0);
|
||||
# endif
|
||||
|
||||
WM_gizmo_modal_set_while_modal(t->region->gizmo_map, t->context, NULL, event);
|
||||
}
|
||||
#endif
|
||||
|
||||
t->mouse.apply = NULL;
|
||||
t->mouse.post = NULL;
|
||||
t->mouse.use_virtual_mval = false;
|
||||
}
|
||||
|
||||
/** \} */
|
|
@ -348,90 +348,6 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_
|
|||
/** \name Transform (Translation) Snapping
|
||||
* \{ */
|
||||
|
||||
static void translate_snap_target_grid_ensure(TransInfo *t)
|
||||
{
|
||||
/* Only need to calculate once. */
|
||||
if ((t->tsnap.status & SNAP_TARGET_GRID_FOUND) == 0) {
|
||||
if (t->data_type == &TransConvertType_Cursor3D) {
|
||||
/* Use a fallback when transforming the cursor.
|
||||
* In this case the center is _not_ derived from the cursor which is being transformed. */
|
||||
copy_v3_v3(t->tsnap.snap_target_grid, TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->data->iloc);
|
||||
}
|
||||
else if (t->around == V3D_AROUND_CURSOR) {
|
||||
/* Use a fallback for cursor selection,
|
||||
* this isn't useful as a global center for absolute grid snapping
|
||||
* since its not based on the position of the selection. */
|
||||
tranform_snap_target_median_calc(t, t->tsnap.snap_target_grid);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(t->tsnap.snap_target_grid, t->center_global);
|
||||
}
|
||||
t->tsnap.status |= SNAP_TARGET_GRID_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
static void translate_snap_grid_apply(TransInfo *t,
|
||||
const int max_index,
|
||||
const float grid_dist[3],
|
||||
const float loc[3],
|
||||
float r_out[3])
|
||||
{
|
||||
BLI_assert(max_index <= 2);
|
||||
translate_snap_target_grid_ensure(t);
|
||||
const float *center_global = t->tsnap.snap_target_grid;
|
||||
const float *asp = t->aspect;
|
||||
|
||||
float in[3];
|
||||
if (t->con.mode & CON_APPLY) {
|
||||
BLI_assert(t->tsnap.snapElem == SCE_SNAP_MODE_NONE);
|
||||
t->con.applyVec(t, NULL, NULL, loc, in);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(in, loc);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= max_index; i++) {
|
||||
const float iter_fac = grid_dist[i] * asp[i];
|
||||
r_out[i] = iter_fac * roundf((in[i] + center_global[i]) / iter_fac) - center_global[i];
|
||||
}
|
||||
}
|
||||
|
||||
static bool translate_snap_grid(TransInfo *t, float *val)
|
||||
{
|
||||
if (!transform_snap_is_active(t)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(t->tsnap.mode & SCE_SNAP_MODE_GRID) || validSnap(t)) {
|
||||
/* Don't do grid snapping if there is a valid snap point. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Don't do grid snapping if not in 3D viewport or UV editor */
|
||||
if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (t->mode != TFM_TRANSLATION) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float grid_dist[3];
|
||||
copy_v3_v3(grid_dist, t->snap_spatial);
|
||||
if (t->modifiers & MOD_PRECISION) {
|
||||
mul_v3_fl(grid_dist, t->snap_spatial_precision);
|
||||
}
|
||||
|
||||
/* Early bailing out if no need to snap */
|
||||
if (is_zero_v3(grid_dist)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
translate_snap_grid_apply(t, t->idx_max, grid_dist, val, val);
|
||||
t->tsnap.snapElem = SCE_SNAP_MODE_GRID;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ApplySnapTranslation(TransInfo *t, float vec[3])
|
||||
{
|
||||
float point[3];
|
||||
|
@ -459,7 +375,7 @@ static void ApplySnapTranslation(TransInfo *t, float vec[3])
|
|||
}
|
||||
}
|
||||
|
||||
sub_v3_v3v3(vec, point, t->tsnap.snap_source);
|
||||
sub_v3_v3v3(vec, point, t->tsnap.snap_source);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -610,7 +526,6 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2]))
|
|||
}
|
||||
|
||||
transform_snap_mixed_apply(t, global_dir);
|
||||
translate_snap_grid(t, global_dir);
|
||||
|
||||
if (t->con.mode & CON_APPLY) {
|
||||
float in[3];
|
||||
|
|
|
@ -609,13 +609,42 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
|
|||
ED_area_status_text(t->area, str);
|
||||
}
|
||||
|
||||
static void vert_slide_transform_matrix_fn(struct TransInfo *t, float mat_xform[4][4])
|
||||
{
|
||||
float delta[3], orig_co[3], final_co[3];
|
||||
|
||||
VertSlideParams *slp = t->custom.mode.data;
|
||||
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
|
||||
VertSlideData *sld_active = tc->custom.mode.data;
|
||||
TransDataVertSlideVert *sv_active = &sld_active->sv[sld_active->curr_sv_index];
|
||||
|
||||
copy_v3_v3(orig_co, sv_active->co_orig_3d);
|
||||
|
||||
float tperc = t->values_final[0];
|
||||
if (slp->use_even) {
|
||||
const float edge_len_curr = len_v3v3(sv_active->co_orig_3d,
|
||||
sv_active->co_link_orig_3d[sv_active->co_link_curr]);
|
||||
tperc *= edge_len_curr;
|
||||
}
|
||||
|
||||
vert_slide_apply_elem(sv_active, tperc, slp->use_even, slp->flipped, final_co);
|
||||
|
||||
if (tc->use_local_mat) {
|
||||
mul_m4_v3(tc->mat, orig_co);
|
||||
mul_m4_v3(tc->mat, final_co);
|
||||
}
|
||||
|
||||
sub_v3_v3v3(delta, final_co, orig_co);
|
||||
add_v3_v3(mat_xform[3], delta);
|
||||
}
|
||||
|
||||
void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp)
|
||||
{
|
||||
|
||||
t->mode = TFM_VERT_SLIDE;
|
||||
t->transform = applyVertSlide;
|
||||
t->handleEvent = handleEventVertSlide;
|
||||
t->transform_matrix = NULL;
|
||||
t->transform_matrix = vert_slide_transform_matrix_fn;
|
||||
t->tsnap.snap_mode_apply_fn = vert_slide_snap_apply;
|
||||
t->tsnap.snap_mode_distance_fn = transform_snap_distance_len_squared_fn;
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "WM_types.h"
|
||||
|
||||
#include "ED_gizmo_library.h"
|
||||
#include "ED_image.h"
|
||||
#include "ED_markers.h"
|
||||
#include "ED_node.h"
|
||||
#include "ED_transform_snap_object_context.h"
|
||||
|
@ -48,6 +49,7 @@
|
|||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "transform.h"
|
||||
#include "transform_constraints.h"
|
||||
#include "transform_convert.h"
|
||||
#include "transform_snap.h"
|
||||
|
||||
|
@ -165,17 +167,33 @@ static bool doForceIncrementSnap(const TransInfo *t)
|
|||
return !transformModeUseSnap(t);
|
||||
}
|
||||
|
||||
static void snap_source_transformed(TransInfo *t, float r_vec[3])
|
||||
{
|
||||
float mat[4][4];
|
||||
unit_m4(mat);
|
||||
if (t->transform_matrix) {
|
||||
t->transform_matrix(t, mat);
|
||||
}
|
||||
|
||||
mul_v3_m4v3(r_vec, mat, t->tsnap.snap_source);
|
||||
}
|
||||
|
||||
void drawSnapping(const struct bContext *C, TransInfo *t)
|
||||
{
|
||||
uchar col[4], selectedCol[4], activeCol[4];
|
||||
if (!transform_snap_is_active(t)) {
|
||||
if (!(transform_snap_is_active(t) || t->modifiers & MOD_EDIT_SNAP_SOURCE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool draw_source = (t->spacetype == SPACE_VIEW3D) && (t->tsnap.status & SNAP_SOURCE_FOUND) &&
|
||||
(t->tsnap.mode & SCE_SNAP_MODE_EDGE_PERPENDICULAR);
|
||||
const bool draw_source = (t->spacetype == SPACE_VIEW3D) &&
|
||||
(t->tsnap.status & SNAP_SOURCE_FOUND) &&
|
||||
(t->tsnap.mode & SCE_SNAP_MODE_EDGE_PERPENDICULAR);
|
||||
|
||||
if (!(draw_source || validSnap(t))) {
|
||||
bool draw_source_transformed = (t->spacetype == SPACE_VIEW3D) &&
|
||||
(t->tsnap.status & SNAP_SOURCE_FOUND) &&
|
||||
!(t->modifiers & MOD_EDIT_SNAP_SOURCE);
|
||||
|
||||
if (!(draw_source || draw_source_transformed || validSnap(t))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -201,8 +219,8 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
|
|||
|
||||
GPU_depth_test(GPU_DEPTH_NONE);
|
||||
|
||||
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
||||
if (!BLI_listbase_is_empty(&t->tsnap.points)) {
|
||||
RegionView3D *rv3d = (RegionView3D *)t->region->regiondata;
|
||||
if (draw_source_transformed || !BLI_listbase_is_empty(&t->tsnap.points)) {
|
||||
/* Draw snap points. */
|
||||
|
||||
float size = 2.0f * UI_GetThemeValuef(TH_VERTEX_SIZE);
|
||||
|
@ -214,14 +232,68 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
|
|||
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
|
||||
LISTBASE_FOREACH (TransSnapPoint *, p, &t->tsnap.points) {
|
||||
if (p == t->tsnap.selectedPoint) {
|
||||
immUniformColor4ubv(selectedCol);
|
||||
float snap_source_tranformed[3];
|
||||
if (draw_source_transformed) {
|
||||
snap_source_transformed(t, snap_source_tranformed);
|
||||
}
|
||||
|
||||
if (!BLI_listbase_is_empty(&t->tsnap.points)) {
|
||||
LISTBASE_FOREACH (TransSnapPoint *, p, &t->tsnap.points) {
|
||||
if (p == t->tsnap.selectedPoint) {
|
||||
immUniformColor4ubv(selectedCol);
|
||||
}
|
||||
else {
|
||||
immUniformColor4ubv(col);
|
||||
}
|
||||
imm_drawcircball(p->co, ED_view3d_pixel_size(rv3d, p->co) * size, view_inv, pos);
|
||||
}
|
||||
else {
|
||||
immUniformColor4ubv(col);
|
||||
|
||||
if (t->modifiers & MOD_EDIT_SNAP_SOURCE) {
|
||||
/* Indicate the new snap source position. */
|
||||
getSnapPoint(t, snap_source_tranformed);
|
||||
draw_source_transformed = true;
|
||||
}
|
||||
imm_drawcircball(p->co, ED_view3d_pixel_size(rv3d, p->co) * size, view_inv, pos);
|
||||
}
|
||||
|
||||
if (draw_source_transformed &&
|
||||
!compare_v3v3(snap_source_tranformed, t->tsnap.snap_target, FLT_EPSILON))
|
||||
{
|
||||
float view_inv[4][4];
|
||||
copy_m4_m4(view_inv, rv3d->viewinv);
|
||||
|
||||
float vx[3], vy[3], v[3];
|
||||
float size_tmp = ED_view3d_pixel_size(rv3d, snap_source_tranformed) * size;
|
||||
float size_fac = 0.5f;
|
||||
|
||||
mul_v3_v3fl(vx, view_inv[0], size_tmp);
|
||||
mul_v3_v3fl(vy, view_inv[1], size_tmp);
|
||||
|
||||
immUniformColor4ubv(col);
|
||||
|
||||
imm_drawcircball(snap_source_tranformed, size_tmp, view_inv, pos);
|
||||
|
||||
immBegin(GPU_PRIM_LINES, 8);
|
||||
add_v3_v3v3(v, snap_source_tranformed, vx);
|
||||
immVertex3fv(pos, v);
|
||||
madd_v3_v3fl(v, vx, size_fac);
|
||||
immVertex3fv(pos, v);
|
||||
|
||||
sub_v3_v3v3(v, snap_source_tranformed, vx);
|
||||
immVertex3fv(pos, v);
|
||||
madd_v3_v3fl(v, vx, -size_fac);
|
||||
immVertex3fv(pos, v);
|
||||
|
||||
add_v3_v3v3(v, snap_source_tranformed, vy);
|
||||
immVertex3fv(pos, v);
|
||||
madd_v3_v3fl(v, vy, size_fac);
|
||||
immVertex3fv(pos, v);
|
||||
|
||||
sub_v3_v3v3(v, snap_source_tranformed, vy);
|
||||
immVertex3fv(pos, v);
|
||||
madd_v3_v3fl(v, vy, -size_fac);
|
||||
immVertex3fv(pos, v);
|
||||
|
||||
immEnd();
|
||||
}
|
||||
|
||||
immUnbindProgram();
|
||||
|
@ -236,7 +308,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
|
|||
loc_prev = t->tsnap.snap_source;
|
||||
}
|
||||
|
||||
if (validSnap(t)) {
|
||||
if (t->tsnap.status & SNAP_TARGET_FOUND) {
|
||||
loc_cur = t->tsnap.snap_target;
|
||||
}
|
||||
|
||||
|
@ -528,7 +600,7 @@ void transform_snap_mixed_apply(TransInfo *t, float *vec)
|
|||
return;
|
||||
}
|
||||
|
||||
if (t->tsnap.mode & ~(SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) {
|
||||
if (t->tsnap.mode != SCE_SNAP_MODE_INCREMENT) {
|
||||
double current = PIL_check_seconds_timer();
|
||||
|
||||
/* Time base quirky code to go around find-nearest slowness. */
|
||||
|
@ -643,14 +715,7 @@ static eSnapMode snap_mode_from_spacetype(TransInfo *t)
|
|||
}
|
||||
|
||||
if (t->spacetype == SPACE_IMAGE) {
|
||||
eSnapMode snap_mode = eSnapMode(ts->snap_uv_mode);
|
||||
if ((snap_mode & SCE_SNAP_MODE_INCREMENT) && (ts->snap_uv_flag & SCE_SNAP_ABS_GRID) &&
|
||||
(t->mode == TFM_TRANSLATION))
|
||||
{
|
||||
snap_mode &= ~SCE_SNAP_MODE_INCREMENT;
|
||||
snap_mode |= SCE_SNAP_MODE_GRID;
|
||||
}
|
||||
return snap_mode;
|
||||
return eSnapMode(ts->snap_uv_mode);
|
||||
}
|
||||
|
||||
if (t->spacetype == SPACE_SEQ) {
|
||||
|
@ -661,16 +726,7 @@ static eSnapMode snap_mode_from_spacetype(TransInfo *t)
|
|||
if (t->options & (CTX_CAMERA | CTX_EDGE_DATA | CTX_PAINT_CURVE)) {
|
||||
return SCE_SNAP_MODE_INCREMENT;
|
||||
}
|
||||
|
||||
eSnapMode snap_mode = eSnapMode(ts->snap_mode);
|
||||
if ((snap_mode & SCE_SNAP_MODE_INCREMENT) && (ts->snap_flag & SCE_SNAP_ABS_GRID) &&
|
||||
(t->mode == TFM_TRANSLATION))
|
||||
{
|
||||
/* Special case in which snap to increments is transformed to snap to grid. */
|
||||
snap_mode &= ~SCE_SNAP_MODE_INCREMENT;
|
||||
snap_mode |= SCE_SNAP_MODE_GRID;
|
||||
}
|
||||
return snap_mode;
|
||||
return eSnapMode(ts->snap_mode);
|
||||
}
|
||||
|
||||
if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA)) {
|
||||
|
@ -733,6 +789,28 @@ static eSnapTargetOP snap_target_select_from_spacetype(TransInfo *t)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void snap_object_context_init(TransInfo *t)
|
||||
{
|
||||
if (t->data_type == &TransConvertType_Mesh) {
|
||||
/* Ignore elements being transformed. */
|
||||
ED_transform_snap_object_context_set_editmesh_callbacks(
|
||||
t->tsnap.object_context,
|
||||
(bool (*)(BMVert *, void *))BM_elem_cb_check_hflag_disabled,
|
||||
bm_edge_is_snap_target,
|
||||
bm_face_is_snap_target,
|
||||
POINTER_FROM_UINT(BM_ELEM_SELECT | BM_ELEM_HIDDEN));
|
||||
}
|
||||
else {
|
||||
/* Ignore hidden geometry in the general case. */
|
||||
ED_transform_snap_object_context_set_editmesh_callbacks(
|
||||
t->tsnap.object_context,
|
||||
(bool (*)(BMVert *, void *))BM_elem_cb_check_hflag_disabled,
|
||||
(bool (*)(BMEdge *, void *))BM_elem_cb_check_hflag_disabled,
|
||||
(bool (*)(BMFace *, void *))BM_elem_cb_check_hflag_disabled,
|
||||
POINTER_FROM_UINT(BM_ELEM_HIDDEN));
|
||||
}
|
||||
}
|
||||
|
||||
static void initSnappingMode(TransInfo *t)
|
||||
{
|
||||
if (!transformModeUseSnap(t)) {
|
||||
|
@ -763,25 +841,7 @@ static void initSnappingMode(TransInfo *t)
|
|||
if (t->tsnap.object_context == nullptr) {
|
||||
SET_FLAG_FROM_TEST(t->tsnap.flag, snap_use_backface_culling(t), SCE_SNAP_BACKFACE_CULLING);
|
||||
t->tsnap.object_context = ED_transform_snap_object_context_create(t->scene, 0);
|
||||
|
||||
if (t->data_type == &TransConvertType_Mesh) {
|
||||
/* Ignore elements being transformed. */
|
||||
ED_transform_snap_object_context_set_editmesh_callbacks(
|
||||
t->tsnap.object_context,
|
||||
(bool (*)(BMVert *, void *))BM_elem_cb_check_hflag_disabled,
|
||||
bm_edge_is_snap_target,
|
||||
bm_face_is_snap_target,
|
||||
POINTER_FROM_UINT(BM_ELEM_SELECT | BM_ELEM_HIDDEN));
|
||||
}
|
||||
else {
|
||||
/* Ignore hidden geometry in the general case. */
|
||||
ED_transform_snap_object_context_set_editmesh_callbacks(
|
||||
t->tsnap.object_context,
|
||||
(bool (*)(BMVert *, void *))BM_elem_cb_check_hflag_disabled,
|
||||
(bool (*)(BMEdge *, void *))BM_elem_cb_check_hflag_disabled,
|
||||
(bool (*)(BMFace *, void *))BM_elem_cb_check_hflag_disabled,
|
||||
POINTER_FROM_UINT(BM_ELEM_HIDDEN));
|
||||
}
|
||||
snap_object_context_init(t);
|
||||
}
|
||||
}
|
||||
else if (t->spacetype == SPACE_SEQ) {
|
||||
|
@ -1075,6 +1135,129 @@ void getSnapPoint(const TransInfo *t, float vec[3])
|
|||
}
|
||||
}
|
||||
|
||||
static void snap_multipoints_free(TransInfo *t)
|
||||
{
|
||||
if (t->tsnap.status & SNAP_MULTI_POINTS) {
|
||||
BLI_freelistN(&t->tsnap.points);
|
||||
t->tsnap.status &= ~SNAP_MULTI_POINTS;
|
||||
t->tsnap.selectedPoint = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Calc Snap
|
||||
* \{ */
|
||||
|
||||
void transform_snap_grid_init(TransInfo *t)
|
||||
{
|
||||
/* Default values. */
|
||||
float grid_dist[3] = {1.0f, 1.0f, 0.0f};
|
||||
float grid_dist_precision = 0.1f;
|
||||
|
||||
if (t->spacetype == SPACE_VIEW3D) {
|
||||
if (t->region->regiondata) {
|
||||
View3D *v3d = static_cast<View3D *>(t->area->spacedata.first);
|
||||
grid_dist[0] = grid_dist[1] = grid_dist[2] = ED_view3d_grid_view_scale(
|
||||
t->scene, v3d, t->region, NULL);
|
||||
}
|
||||
}
|
||||
else if (t->spacetype == SPACE_IMAGE) {
|
||||
SpaceImage *sima = static_cast<SpaceImage *>(t->area->spacedata.first);
|
||||
View2D *v2d = &t->region->v2d;
|
||||
int grid_size = SI_GRID_STEPS_LEN;
|
||||
float zoom_factor = ED_space_image_zoom_level(v2d, grid_size);
|
||||
float grid_steps_x[SI_GRID_STEPS_LEN];
|
||||
float grid_steps_y[SI_GRID_STEPS_LEN];
|
||||
|
||||
ED_space_image_grid_steps(sima, grid_steps_x, grid_steps_y, grid_size);
|
||||
/* Snapping value based on what type of grid is used (adaptive-subdividing or custom-grid). */
|
||||
grid_dist[0] = ED_space_image_increment_snap_value(grid_size, grid_steps_x, zoom_factor);
|
||||
grid_dist[1] = ED_space_image_increment_snap_value(grid_size, grid_steps_y, zoom_factor);
|
||||
grid_dist_precision = 0.5f;
|
||||
}
|
||||
else if (t->spacetype == SPACE_CLIP) {
|
||||
grid_dist[0] = grid_dist[1] = 0.125f;
|
||||
grid_dist_precision = 0.5f;
|
||||
}
|
||||
else if (t->spacetype == SPACE_NODE) {
|
||||
grid_dist[0] = grid_dist[1] = ED_node_grid_size();
|
||||
}
|
||||
|
||||
copy_v3_v3(t->snap_spatial, grid_dist);
|
||||
t->snap_spatial_precision = grid_dist_precision;
|
||||
|
||||
if (t->mode == TFM_TRANSLATION) {
|
||||
/* WORKAROUND: Reset incremental snap values. */
|
||||
t->snap[0] = t->snap_spatial[0];
|
||||
t->snap[1] = t->snap_spatial[0] * t->snap_spatial_precision;
|
||||
}
|
||||
}
|
||||
|
||||
static bool snap_grid(TransInfo *t, const float mval[2], const int val_size, float *r_val)
|
||||
{
|
||||
float grid_dist[3];
|
||||
copy_v3_v3(grid_dist, t->snap_spatial);
|
||||
if (t->modifiers & MOD_PRECISION) {
|
||||
mul_v3_fl(grid_dist, t->snap_spatial_precision);
|
||||
}
|
||||
|
||||
/* Early bailing out if no need to snap */
|
||||
if (is_zero_v3(grid_dist)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (t->spacetype == SPACE_VIEW3D) {
|
||||
float ray_dir[3];
|
||||
ED_view3d_win_to_ray_clipped(
|
||||
t->depsgraph, t->region, (View3D *)t->view, mval, r_val, ray_dir, true);
|
||||
|
||||
if ((t->mode != TFM_ROTATION) && (t->con.mode & CON_APPLY)) {
|
||||
if (!transform_constraint_isect_ray(t, r_val, ray_dir, r_val)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
float lambda;
|
||||
float plane[4];
|
||||
if (t->persp != RV3D_ORTHO) {
|
||||
/* Intersect Plane Z. */
|
||||
copy_v4_fl4(plane, 0.0f, 0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
else {
|
||||
plane_from_point_normal_v3(plane, t->center_global, ray_dir);
|
||||
}
|
||||
|
||||
if (isect_ray_plane_v3(r_val, ray_dir, plane, &lambda, true)) {
|
||||
madd_v3_v3fl(r_val, ray_dir, lambda);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const View2D *v2d = &t->region->v2d;
|
||||
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]);
|
||||
|
||||
sub_v2_v2v2(r_val, mval, offset);
|
||||
r_val[0] /= scale[0];
|
||||
r_val[1] /= scale[1];
|
||||
}
|
||||
|
||||
/* Apply. */
|
||||
for (int i = 0; i < val_size; i++) {
|
||||
const float iter_fac = grid_dist[i] * t->aspect[i];
|
||||
r_val[i] = iter_fac * roundf(r_val[i] / iter_fac);
|
||||
}
|
||||
|
||||
t->tsnap.snapElem = SCE_SNAP_MODE_GRID;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -1087,28 +1270,31 @@ static void snap_target_view3d_fn(TransInfo *t, float * /*vec*/)
|
|||
float loc[3];
|
||||
float no[3];
|
||||
float mval[2];
|
||||
bool found = false;
|
||||
eSnapMode snap_elem = SCE_SNAP_MODE_NONE;
|
||||
float dist_px = SNAP_MIN_DISTANCE; /* Use a user defined value here. */
|
||||
|
||||
zero_v3(no); /* objects won't set this */
|
||||
mval[0] = t->mval[0];
|
||||
mval[1] = t->mval[1];
|
||||
|
||||
if (t->tsnap.mode & SCE_SNAP_MODE_GEOM) {
|
||||
zero_v3(no); /* objects won't set this */
|
||||
snap_elem = snapObjectsTransform(t, mval, &dist_px, loc, no);
|
||||
found = (snap_elem != SCE_SNAP_MODE_NONE);
|
||||
}
|
||||
if ((found == false) && (t->tsnap.mode & SCE_SNAP_MODE_VOLUME)) {
|
||||
bool use_peel = (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0;
|
||||
found = peelObjectsTransform(t, mval, use_peel, loc, no, nullptr);
|
||||
|
||||
if (found) {
|
||||
if ((snap_elem == SCE_SNAP_MODE_NONE) && (t->tsnap.mode & SCE_SNAP_MODE_VOLUME)) {
|
||||
bool use_peel = (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0;
|
||||
if (peelObjectsTransform(t, mval, use_peel, loc, no, nullptr)) {
|
||||
snap_elem = SCE_SNAP_MODE_VOLUME;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == true) {
|
||||
if ((snap_elem == SCE_SNAP_MODE_NONE) && (t->tsnap.mode & SCE_SNAP_MODE_GRID)) {
|
||||
if (snap_grid(t, mval, 3, loc)) {
|
||||
snap_elem = SCE_SNAP_MODE_GRID;
|
||||
}
|
||||
}
|
||||
|
||||
if (snap_elem != SCE_SNAP_MODE_NONE) {
|
||||
copy_v3_v3(t->tsnap.snap_target, loc);
|
||||
copy_v3_v3(t->tsnap.snapNormal, no);
|
||||
|
||||
|
@ -1124,6 +1310,8 @@ static void snap_target_view3d_fn(TransInfo *t, float * /*vec*/)
|
|||
static void snap_target_uv_fn(TransInfo *t, float * /*vec*/)
|
||||
{
|
||||
BLI_assert(t->spacetype == SPACE_IMAGE);
|
||||
|
||||
eSnapMode snap_elem = SCE_SNAP_MODE_NONE;
|
||||
if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) {
|
||||
uint objects_len = 0;
|
||||
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
|
||||
|
@ -1142,13 +1330,22 @@ static void snap_target_uv_fn(TransInfo *t, float * /*vec*/)
|
|||
t->tsnap.snap_target[0] *= t->aspect[0];
|
||||
t->tsnap.snap_target[1] *= t->aspect[1];
|
||||
|
||||
t->tsnap.status |= SNAP_TARGET_FOUND;
|
||||
}
|
||||
else {
|
||||
t->tsnap.status &= ~SNAP_TARGET_FOUND;
|
||||
snap_elem = SCE_SNAP_MODE_VERTEX;
|
||||
}
|
||||
MEM_freeN(objects);
|
||||
}
|
||||
|
||||
if ((snap_elem == SCE_SNAP_MODE_NONE) && (t->tsnap.mode & SCE_SNAP_MODE_GRID)) {
|
||||
float mval[2];
|
||||
mval[0] = t->mval[0];
|
||||
mval[1] = t->mval[1];
|
||||
if (snap_grid(t, mval, 2, t->tsnap.snap_target)) {
|
||||
snap_elem = SCE_SNAP_MODE_GRID;
|
||||
}
|
||||
}
|
||||
|
||||
SET_FLAG_FROM_TEST(t->tsnap.status, snap_elem != SCE_SNAP_MODE_NONE, SNAP_TARGET_FOUND);
|
||||
t->tsnap.snapElem = snap_elem;
|
||||
}
|
||||
|
||||
static void snap_target_node_fn(TransInfo *t, float * /*vec*/)
|
||||
|
@ -1616,7 +1813,7 @@ bool snapNodesTransform(
|
|||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name snap Grid
|
||||
/** \name snap Increment
|
||||
* \{ */
|
||||
|
||||
static void snap_increment_apply_ex(const TransInfo * /*t*/,
|
||||
|
@ -1713,6 +1910,12 @@ float transform_snap_increment_get(const TransInfo *t)
|
|||
return 0.0f;
|
||||
}
|
||||
|
||||
void tranform_snap_source_restore_context(TransInfo *t)
|
||||
{
|
||||
snap_object_context_init(t);
|
||||
snap_multipoints_free(t);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -38,11 +38,15 @@ bool snapNodesTransform(struct TransInfo *t,
|
|||
|
||||
bool transformModeUseSnap(const TransInfo *t);
|
||||
|
||||
void transform_snap_grid_init(TransInfo *t);
|
||||
|
||||
void tranform_snap_target_median_calc(const TransInfo *t, float r_median[3]);
|
||||
bool transform_snap_increment_ex(const TransInfo *t, bool use_local_space, float *r_val);
|
||||
bool transform_snap_increment(const TransInfo *t, float *val);
|
||||
float transform_snap_increment_get(const TransInfo *t);
|
||||
|
||||
void tranform_snap_source_restore_context(TransInfo *t);
|
||||
|
||||
void transform_snap_flag_from_modifiers_set(TransInfo *t);
|
||||
bool transform_snap_is_active(const TransInfo *t);
|
||||
|
||||
|
|
|
@ -298,7 +298,7 @@ static SnapData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx,
|
|||
else if (sod->mesh_runtime) {
|
||||
if (sod->mesh_runtime != snap_object_data_editmesh_runtime_get(ob_eval)) {
|
||||
if (G.moving) {
|
||||
/* Hack to avoid updating while transforming. */
|
||||
/* WORKAROUND: avoid updating while transforming. */
|
||||
BLI_assert(!sod->treedata_editmesh.cached && !sod->cached[0] && !sod->cached[1]);
|
||||
sod->mesh_runtime = snap_object_data_editmesh_runtime_get(ob_eval);
|
||||
}
|
||||
|
@ -381,11 +381,12 @@ static BVHTreeFromEditMesh *snap_object_data_editmesh_treedata_get(SnapObjectCon
|
|||
em,
|
||||
4,
|
||||
BVHTREE_FROM_EM_LOOPTRI,
|
||||
&sod->mesh_runtime->bvh_cache,
|
||||
/* WORKAROUND: avoid updating while transforming. */
|
||||
G.moving ? nullptr : &sod->mesh_runtime->bvh_cache,
|
||||
&sod->mesh_runtime->eval_mutex);
|
||||
}
|
||||
}
|
||||
if (treedata == nullptr || treedata->tree == nullptr) {
|
||||
if (treedata->tree == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1263,7 +1264,7 @@ static bool nearest_world_editmesh(SnapObjectContext *sctx,
|
|||
int *r_index)
|
||||
{
|
||||
BVHTreeFromEditMesh *treedata = snap_object_data_editmesh_treedata_get(sctx, ob_eval, em);
|
||||
if (treedata == nullptr || treedata->tree == nullptr) {
|
||||
if (treedata == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2765,7 +2766,8 @@ static eSnapMode snapEditMesh(SnapObjectContext *sctx,
|
|||
em,
|
||||
2,
|
||||
BVHTREE_FROM_EM_VERTS,
|
||||
&sod->mesh_runtime->bvh_cache,
|
||||
/* WORKAROUND: avoid updating while transforming. */
|
||||
G.moving ? nullptr : &sod->mesh_runtime->bvh_cache,
|
||||
&sod->mesh_runtime->eval_mutex);
|
||||
}
|
||||
sod->bvhtree[0] = treedata.tree;
|
||||
|
@ -2794,7 +2796,8 @@ static eSnapMode snapEditMesh(SnapObjectContext *sctx,
|
|||
em,
|
||||
2,
|
||||
BVHTREE_FROM_EM_EDGES,
|
||||
&sod->mesh_runtime->bvh_cache,
|
||||
/* WORKAROUND: avoid updating while transforming. */
|
||||
G.moving ? nullptr : &sod->mesh_runtime->bvh_cache,
|
||||
&sod->mesh_runtime->eval_mutex);
|
||||
}
|
||||
sod->bvhtree[1] = treedata.tree;
|
||||
|
@ -3063,11 +3066,27 @@ void ED_transform_snap_object_context_set_editmesh_callbacks(
|
|||
bool (*test_face_fn)(BMFace *, void *user_data),
|
||||
void *user_data)
|
||||
{
|
||||
sctx->callbacks.edit_mesh.test_vert_fn = test_vert_fn;
|
||||
sctx->callbacks.edit_mesh.test_edge_fn = test_edge_fn;
|
||||
sctx->callbacks.edit_mesh.test_face_fn = test_face_fn;
|
||||
bool is_cache_dirty = false;
|
||||
if (sctx->callbacks.edit_mesh.test_vert_fn != test_vert_fn) {
|
||||
sctx->callbacks.edit_mesh.test_vert_fn = test_vert_fn;
|
||||
is_cache_dirty = true;
|
||||
}
|
||||
if (sctx->callbacks.edit_mesh.test_edge_fn != test_edge_fn) {
|
||||
sctx->callbacks.edit_mesh.test_edge_fn = test_edge_fn;
|
||||
is_cache_dirty = true;
|
||||
}
|
||||
if (sctx->callbacks.edit_mesh.test_face_fn != test_face_fn) {
|
||||
sctx->callbacks.edit_mesh.test_face_fn = test_face_fn;
|
||||
is_cache_dirty = true;
|
||||
}
|
||||
if (sctx->callbacks.edit_mesh.user_data != user_data) {
|
||||
sctx->callbacks.edit_mesh.user_data = user_data;
|
||||
is_cache_dirty = true;
|
||||
}
|
||||
|
||||
sctx->callbacks.edit_mesh.user_data = user_data;
|
||||
if (is_cache_dirty) {
|
||||
sctx->editmesh_caches.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx,
|
||||
|
|
|
@ -2257,7 +2257,7 @@ typedef enum eSnapFlag {
|
|||
SCE_SNAP_PROJECT = (1 << 3),
|
||||
/** Was `SCE_SNAP_NO_SELF`, but self should be active. */
|
||||
SCE_SNAP_NOT_TO_ACTIVE = (1 << 4),
|
||||
SCE_SNAP_ABS_GRID = (1 << 5),
|
||||
/* SCE_SNAP_ABS_GRID = (1 << 5), */ /* UNUSED */
|
||||
SCE_SNAP_BACKFACE_CULLING = (1 << 6),
|
||||
SCE_SNAP_KEEP_ON_SAME_OBJECT = (1 << 7),
|
||||
/** see #eSnapTargetOP */
|
||||
|
|
|
@ -150,11 +150,8 @@ const EnumPropertyItem rna_enum_mesh_select_mode_uv_items[] = {
|
|||
};
|
||||
|
||||
const EnumPropertyItem rna_enum_snap_element_items[] = {
|
||||
{SCE_SNAP_MODE_INCREMENT,
|
||||
"INCREMENT",
|
||||
ICON_SNAP_INCREMENT,
|
||||
"Increment",
|
||||
"Snap to increments of grid"},
|
||||
{SCE_SNAP_MODE_INCREMENT, "INCREMENT", ICON_SNAP_INCREMENT, "Increment", "Snap to increments"},
|
||||
{SCE_SNAP_MODE_GRID, "GRID", ICON_SNAP_GRID, "Grid", "Snap to grid"},
|
||||
{SCE_SNAP_MODE_VERTEX, "VERTEX", ICON_SNAP_VERTEX, "Vertex", "Snap to vertices"},
|
||||
{SCE_SNAP_MODE_EDGE, "EDGE", ICON_SNAP_EDGE, "Edge", "Snap to edges"},
|
||||
{SCE_SNAP_MODE_FACE_RAYCAST,
|
||||
|
@ -195,11 +192,8 @@ const EnumPropertyItem rna_enum_snap_node_element_items[] = {
|
|||
|
||||
#ifndef RNA_RUNTIME
|
||||
static const EnumPropertyItem snap_uv_element_items[] = {
|
||||
{SCE_SNAP_MODE_INCREMENT,
|
||||
"INCREMENT",
|
||||
ICON_SNAP_INCREMENT,
|
||||
"Increment",
|
||||
"Snap to increments of grid"},
|
||||
{SCE_SNAP_MODE_INCREMENT, "INCREMENT", ICON_SNAP_INCREMENT, "Increment", "Snap to increments"},
|
||||
{SCE_SNAP_MODE_GRID, "GRID", ICON_SNAP_GRID, "Grid", "Snap to grid"},
|
||||
{SCE_SNAP_MODE_VERTEX, "VERTEX", ICON_SNAP_VERTEX, "Vertex", "Snap to vertices"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
@ -3383,14 +3377,6 @@ static void rna_def_tool_settings(BlenderRNA *brna)
|
|||
prop, "Align Rotation to Target", "Align rotation with the snapping target");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
|
||||
|
||||
prop = RNA_def_property(srna, "use_snap_grid_absolute", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_ABS_GRID);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Absolute Grid Snap",
|
||||
"Absolute grid alignment while translating (based on the pivot center)");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
|
||||
|
||||
prop = RNA_def_property(srna, "snap_elements", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_mode");
|
||||
RNA_def_property_enum_items(prop, rna_enum_snap_element_items);
|
||||
|
@ -3428,14 +3414,6 @@ static void rna_def_tool_settings(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Snap UV Element", "Type of element to snap to");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
|
||||
|
||||
prop = RNA_def_property(srna, "use_snap_uv_grid_absolute", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "snap_uv_flag", SCE_SNAP_ABS_GRID);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Absolute Grid Snap",
|
||||
"Absolute grid alignment while translating (based on the pivot center)");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
|
||||
|
||||
/* TODO(@gfxcoder): Rename `snap_target` to `snap_source` to avoid previous ambiguity of "target"
|
||||
* (now, "source" is geometry to be moved and "target" is geometry to which moved geometry is
|
||||
* snapped). */
|
||||
|
|
Loading…
Reference in New Issue