Transform: Support mixed snap in 3d View.

Allows more than one snap mode to be enabled. So different combinations are possible.

Reviewers: campbellbarton

Reviewed By: campbellbarton

Subscribers: Christopher_Anderssarian, duarteframos

Tags: #bf_blender_2.8

Differential Revision: D3400
This commit is contained in:
Germano Cavalcante 2018-05-22 08:58:56 -03:00
parent 47b9d7494e
commit f99197fb2d
16 changed files with 211 additions and 193 deletions

View File

@ -259,8 +259,14 @@ class TOPBAR_HT_lower_bar(Header):
show_snap = True
if show_snap:
snap_element = toolsettings.snap_element
act_snap_element = bpy.types.ToolSettings.bl_rna.properties['snap_element'].enum_items[snap_element]
snap_items = bpy.types.ToolSettings.bl_rna.properties['snap_elements'].enum_items
for elem in toolsettings.snap_elements:
# TODO: Display multiple icons.
# (Currently only one of the enabled modes icons is displayed)
icon = snap_items[elem].icon
break
else:
icon = 'NONE'
row = layout.row(align=True)
row.prop(toolsettings, "use_snap", text="")
@ -270,7 +276,7 @@ class TOPBAR_HT_lower_bar(Header):
space_type='TOPBAR',
region_type='HEADER',
panel_type="TOPBAR_PT_snapping",
icon=act_snap_element.icon,
icon=icon,
text=""
)
@ -367,7 +373,7 @@ class TOPBAR_PT_snapping(Panel):
def draw(self, context):
toolsettings = context.tool_settings
snap_element = toolsettings.snap_element
snap_elements = toolsettings.snap_elements
obj = context.active_object
mode = context.mode
object_mode = 'OBJECT' if obj is None else obj.mode
@ -375,13 +381,13 @@ class TOPBAR_PT_snapping(Panel):
layout = self.layout
col = layout.column()
col.label("Snapping")
col.prop(toolsettings, "snap_element", expand=True)
col.prop(toolsettings, "snap_elements", expand=True)
col.separator()
if snap_element == 'INCREMENT':
if 'INCREMENT' in snap_elements:
col.prop(toolsettings, "use_snap_grid_absolute")
else:
if snap_elements != {'INCREMENT'}:
col.label("Target")
row = col.row(align=True)
row.prop(toolsettings, "snap_target", expand=True)
@ -389,13 +395,14 @@ class TOPBAR_PT_snapping(Panel):
if obj:
if object_mode == 'EDIT':
col.prop(toolsettings, "use_snap_self")
if object_mode in {'OBJECT', 'POSE', 'EDIT'} and snap_element != 'VOLUME':
if object_mode in {'OBJECT', 'POSE', 'EDIT'}:
col.prop(toolsettings, "use_snap_align_rotation", text="Align Rotation")
if snap_element == 'VOLUME':
col.prop(toolsettings, "use_snap_peel_object")
elif snap_element == 'FACE':
col.prop(toolsettings, "use_snap_project", text="Project Elements")
if 'FACE' in snap_elements:
col.prop(toolsettings, "use_snap_project", text="Project Elements")
if 'VOLUME' in snap_elements:
col.prop(toolsettings, "use_snap_peel_object")
# Auto-Merge Editing
if obj:

View File

@ -28,7 +28,7 @@
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 280
#define BLENDER_SUBVERSION 14
#define BLENDER_SUBVERSION 15
/* Several breakages with 270, e.g. constraint deg vs rad */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 6

View File

@ -642,7 +642,9 @@ void BKE_scene_init(Scene *sce)
sce->toolsettings->transform_pivot_point = V3D_AROUND_CENTER_MEAN;
sce->toolsettings->snap_mode = SCE_SNAP_MODE_INCREMENT;
sce->toolsettings->snap_node_mode = SCE_SNAP_MODE_GRID;
sce->toolsettings->snap_uv_mode = SCE_SNAP_MODE_INCREMENT;
sce->toolsettings->curve_paint_settings.curve_type = CU_BEZIER;
sce->toolsettings->curve_paint_settings.flag |= CURVE_PAINT_FLAG_CORNERS_DETECT;

View File

@ -1477,5 +1477,25 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
}
for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
switch (scene->toolsettings->snap_mode) {
case 0: scene->toolsettings->snap_mode = SCE_SNAP_MODE_INCREMENT; break;
case 1: scene->toolsettings->snap_mode = SCE_SNAP_MODE_VERTEX ; break;
case 2: scene->toolsettings->snap_mode = SCE_SNAP_MODE_EDGE ; break;
case 3: scene->toolsettings->snap_mode = SCE_SNAP_MODE_FACE ; break;
case 4: scene->toolsettings->snap_mode = SCE_SNAP_MODE_VOLUME ; break;
}
switch (scene->toolsettings->snap_node_mode) {
case 5: scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_NODE_X; break;
case 6: scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_NODE_Y; break;
case 7: scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y; break;
case 8: scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_GRID ; break;
}
switch (scene->toolsettings->snap_uv_mode) {
case 0: scene->toolsettings->snap_uv_mode = SCE_SNAP_MODE_INCREMENT; break;
case 1: scene->toolsettings->snap_uv_mode = SCE_SNAP_MODE_VERTEX ; break;
}
}
}
}

View File

@ -5015,9 +5015,9 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
CTX_data_main(C), vc.scene, CTX_data_depsgraph(C), 0, vc.ar, vc.v3d);
ED_transform_snap_object_project_view3d_mixed(
ED_transform_snap_object_project_view3d(
snap_context,
SCE_SELECT_FACE,
SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
.snap_select = (vc.obedit != NULL) ? SNAP_NOT_ACTIVE : SNAP_ALL,
.use_object_edit_cage = false,

View File

@ -128,12 +128,6 @@ bool ED_transform_snap_object_project_view3d(
const float mval[2], float *dist_px,
/* return args */
float r_loc[3], float r_no[3]);
bool ED_transform_snap_object_project_view3d_mixed(
SnapObjectContext *sctx,
const unsigned short snap_to_flag,
const struct SnapObjectParams *params,
const float mval_fl[2], float *dist_px,
float r_co[3], float r_no[3]);
bool ED_transform_snap_object_project_all_view3d_ex(
SnapObjectContext *sctx,

View File

@ -373,9 +373,9 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
float mval[2], co_proj[3];
if (ED_view3d_project_float_object(ar, eve->co, mval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
if (ED_transform_snap_object_project_view3d_mixed(
if (ED_transform_snap_object_project_view3d(
snap_context,
SCE_SELECT_FACE,
SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
.snap_select = SNAP_NOT_ACTIVE,
.use_object_edit_cage = false,

View File

@ -320,9 +320,9 @@ static bool view3d_ruler_item_mousemove(
co_other = ruler_item->co[inter->co_index == 0 ? 2 : 0];
if (ED_transform_snap_object_project_view3d_mixed(
if (ED_transform_snap_object_project_view3d(
ruler_info->snap_context,
SCE_SELECT_FACE,
SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
.use_object_edit_cage = true,
@ -346,9 +346,9 @@ static bool view3d_ruler_item_mousemove(
else if (do_snap) {
const float mval_fl[2] = {UNPACK2(mval)};
if (ED_transform_snap_object_project_view3d_mixed(
if (ED_transform_snap_object_project_view3d(
ruler_info->snap_context,
(SCE_SELECT_VERTEX | SCE_SELECT_EDGE | SCE_SELECT_FACE),
(SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE),
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
.use_object_edit_cage = true,

View File

@ -761,9 +761,9 @@ static bool view3d_ruler_item_mousemove(
co_other = ruler_item->co[ruler_item->co_index == 0 ? 2 : 0];
if (ED_transform_snap_object_project_view3d_mixed(
if (ED_transform_snap_object_project_view3d(
ruler_info->snap_context,
SCE_SELECT_FACE,
SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
.use_object_edit_cage = true,
@ -787,9 +787,9 @@ static bool view3d_ruler_item_mousemove(
else if (do_snap) {
const float mval_fl[2] = {UNPACK2(mval)};
if (ED_transform_snap_object_project_view3d_mixed(
if (ED_transform_snap_object_project_view3d(
ruler_info->snap_context,
(SCE_SELECT_VERTEX | SCE_SELECT_EDGE | SCE_SELECT_FACE),
(SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE),
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
.use_object_edit_cage = true,

View File

@ -3007,7 +3007,7 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
#else
/* hrmf, snapping radius is using 'angle' steps, need to convert to something else
* this isnt essential but nicer to give reasonable snapping values for radius */
if (t->tsnap.mode == SCE_SNAP_MODE_INCREMENT) {
if (t->tsnap.mode & SCE_SNAP_MODE_INCREMENT) {
const float radius_snap = 0.1f;
const float snap_hack = (t->snap[1] * data->warp_init_dist) / radius_snap;
values.scale *= snap_hack;

View File

@ -881,7 +881,6 @@ void projectVertSlideData(TransInfo *t, bool is_final);
/* TODO. transform_queries.c */
bool checkUseAxisMatrix(TransInfo *t);
#define TRANSFORM_DIST_MAX_PX 1000.0f
#define TRANSFORM_SNAP_MAX_PX 100.0f
#define TRANSFORM_DIST_INVALID -FLT_MAX

View File

@ -343,8 +343,7 @@ static void applyAxisConstraintVec(
mul_m3_v3(t->con.pmtx, out);
// With snap, a projection is alright, no need to correct for view alignment
if (!(!ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID) && activeSnap(t))) {
if (!validSnap(t)) {
const int dims = getConstraintSpaceDimension(t);
if (dims == 2) {
if (!is_zero_v3(out)) {

View File

@ -280,7 +280,6 @@ void applyProject(TransInfo *t)
for (i = 0; i < tc->data_len; i++, td++) {
float iloc[3], loc[3], no[3];
float mval_fl[2];
float dist_px = TRANSFORM_DIST_MAX_PX;
if (td->flag & TD_NOACTION)
break;
@ -301,9 +300,15 @@ void applyProject(TransInfo *t)
}
if (ED_view3d_project_float_global(t->ar, iloc, mval_fl, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
if (snapObjectsTransform(
t, mval_fl, &dist_px,
loc, no))
if (ED_transform_snap_object_project_view3d(
t->tsnap.object_context,
SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
.snap_select = t->tsnap.modeSelect,
.use_object_edit_cage = (t->flag & T_EDIT) != 0,
.use_occlusion_test = false,
},
mval_fl, 0, loc, no))
{
#if 0
if (tc->use_local_mat) {
@ -346,7 +351,7 @@ void applyGridAbsolute(TransInfo *t)
GearsType grid_action;
int i;
if (!(activeSnap(t) && (ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID))))
if (!(activeSnap(t) && (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID))))
return;
grid_action = BIG_GEARS;
@ -401,16 +406,20 @@ void applyGridAbsolute(TransInfo *t)
void applySnapping(TransInfo *t, float *vec)
{
/* project is not applied this way */
if (t->tsnap.project)
if (t->tsnap.project && t->tsnap.mode == SCE_SNAP_MODE_FACE) {
/* Each Trans Data already makes the snap to face */
return;
}
if (t->tsnap.status & SNAP_FORCED) {
t->tsnap.targetSnap(t);
t->tsnap.applySnap(t, vec);
}
else if (!ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID) && activeSnap(t)) {
else if ((t->tsnap.mode &
~(SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID) != 0) &&
activeSnap(t))
{
double current = PIL_check_seconds_timer();
// Time base quirky code to go around findnearest slowness
@ -512,7 +521,7 @@ static void initSnappingMode(TransInfo *t)
}
else {
/* force project off when not supported */
if (ts->snap_mode != SCE_SNAP_MODE_FACE)
if ((ts->snap_mode & SCE_SNAP_MODE_FACE) == 0)
t->tsnap.project = 0;
t->tsnap.mode = ts->snap_mode;
@ -948,18 +957,22 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
mval[0] = t->mval[0];
mval[1] = t->mval[1];
if (t->tsnap.mode == SCE_SNAP_MODE_VOLUME) {
found = peelObjectsTransform(
t, mval,
(t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0,
loc, no, NULL);
}
else {
if (t->tsnap.mode &
(SCE_SNAP_MODE_VERTEX |
SCE_SNAP_MODE_EDGE |
SCE_SNAP_MODE_FACE))
{
zero_v3(no); /* objects won't set this */
found = snapObjectsTransform(
t, mval, &dist_px,
loc, no);
}
if ((found == false) && (t->tsnap.mode & SCE_SNAP_MODE_VOLUME)) {
found = peelObjectsTransform(
t, mval,
(t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0,
loc, no, NULL);
}
if (found == true) {
copy_v3_v3(t->tsnap.snapPoint, loc);
@ -972,35 +985,38 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
}
}
else if (t->spacetype == SPACE_IMAGE && t->obedit_type == OB_MESH) {
/* same as above but for UV's */
Image *ima = ED_space_image(t->sa->spacedata.first);
float co[2];
if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) {
Image *ima = ED_space_image(t->sa->spacedata.first);
float co[2];
UI_view2d_region_to_view(&t->ar->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
UI_view2d_region_to_view(&t->ar->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
if (ED_uvedit_nearest_uv(t->scene, TRANS_DATA_CONTAINER_FIRST_EVIL(t)->obedit, ima, co, t->tsnap.snapPoint)) {
t->tsnap.snapPoint[0] *= t->aspect[0];
t->tsnap.snapPoint[1] *= t->aspect[1];
if (ED_uvedit_nearest_uv(t->scene, TRANS_DATA_CONTAINER_FIRST_EVIL(t)->obedit, ima, co, t->tsnap.snapPoint)) {
t->tsnap.snapPoint[0] *= t->aspect[0];
t->tsnap.snapPoint[1] *= t->aspect[1];
t->tsnap.status |= POINT_INIT;
}
else {
t->tsnap.status &= ~POINT_INIT;
t->tsnap.status |= POINT_INIT;
}
else {
t->tsnap.status &= ~POINT_INIT;
}
}
}
else if (t->spacetype == SPACE_NODE) {
float loc[2];
float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
char node_border;
if (t->tsnap.mode & (SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y)) {
float loc[2];
float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
char node_border;
if (snapNodesTransform(t, t->mval, loc, &dist_px, &node_border)) {
copy_v2_v2(t->tsnap.snapPoint, loc);
t->tsnap.snapNodeBorder = node_border;
if (snapNodesTransform(t, t->mval, loc, &dist_px, &node_border)) {
copy_v2_v2(t->tsnap.snapPoint, loc);
t->tsnap.snapNodeBorder = node_border;
t->tsnap.status |= POINT_INIT;
}
else {
t->tsnap.status &= ~POINT_INIT;
t->tsnap.status |= POINT_INIT;
}
else {
t->tsnap.status &= ~POINT_INIT;
}
}
}
}
@ -1309,15 +1325,14 @@ static bool snapNodeTest(View2D *v2d, bNode *node, eSnapSelect snap_select)
static NodeBorder snapNodeBorder(int snap_node_mode)
{
switch (snap_node_mode) {
case SCE_SNAP_MODE_NODE_X:
return NODE_LEFT | NODE_RIGHT;
case SCE_SNAP_MODE_NODE_Y:
return NODE_TOP | NODE_BOTTOM;
case SCE_SNAP_MODE_NODE_XY:
return NODE_LEFT | NODE_RIGHT | NODE_TOP | NODE_BOTTOM;
NodeBorder flag = 0;
if (snap_node_mode & SCE_SNAP_MODE_NODE_X) {
flag |= NODE_LEFT | NODE_RIGHT;
}
return 0;
if (snap_node_mode & SCE_SNAP_MODE_NODE_Y) {
flag |= NODE_TOP | NODE_BOTTOM;
}
return flag;
}
static bool snapNode(
@ -1425,9 +1440,13 @@ void snapGridIncrement(TransInfo *t, float *val)
{
GearsType action;
/* only do something if using absolute or incremental grid snapping */
if (!ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID))
/* only do something if using absolute or incremental grid snapping
* and there is no valid snap point */
if (!(t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) ||
validSnap(t))
{
return;
}
action = activeSnap(t) ? BIG_GEARS : NO_GEARS;
@ -1467,7 +1486,7 @@ static void applyGridIncrement(TransInfo *t, float *val, int max_index, const fl
const float *asp = use_aspect ? t->aspect : asp_local;
int i;
BLI_assert(ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID));
BLI_assert(t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID));
BLI_assert(max_index <= 2);
/* Early bailing out if no need to snap */

View File

@ -1125,8 +1125,8 @@ static short snap_mesh_polygon(
MPoly *mp = &((Mesh *)ob->data)->mpoly[*r_index];
const MLoop *ml;
if (snapdata->snap_to_flag & SCE_SELECT_EDGE) {
elem = SCE_SELECT_EDGE;
if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
elem = SCE_SNAP_MODE_EDGE;
treedata->edge = ((Mesh *)ob->data)->medge;
ml = &treedata->loop[mp->loopstart];
for (int i = mp->totloop; i--; ml++) {
@ -1137,7 +1137,7 @@ static short snap_mesh_polygon(
}
}
else {
elem = SCE_SELECT_VERTEX;
elem = SCE_SNAP_MODE_VERTEX;
ml = &treedata->loop[mp->loopstart];
for (int i = mp->totloop; i--; ml++) {
cb_snap_vert(
@ -1160,8 +1160,8 @@ static short snap_mesh_polygon(
BMFace *f = BM_face_at_index(em->bm, *r_index);
BMLoop *l_iter, *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
if (snapdata->snap_to_flag & SCE_SELECT_EDGE) {
elem = SCE_SELECT_EDGE;
if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
elem = SCE_SNAP_MODE_EDGE;
BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE);
do {
cb_snap_edge(
@ -1172,7 +1172,7 @@ static short snap_mesh_polygon(
} while ((l_iter = l_iter->next) != l_first);
}
else {
elem = SCE_SELECT_VERTEX;
elem = SCE_SNAP_MODE_VERTEX;
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
do {
cb_snap_vert(
@ -1218,7 +1218,7 @@ static short snap_mesh_edge_verts_mixed(
/* return args */
float r_loc[3], float r_no[3], int *r_index)
{
short elem = SCE_SELECT_EDGE;
short elem = SCE_SNAP_MODE_EDGE;
if (ob->type != OB_MESH) {
return elem;
@ -1282,7 +1282,7 @@ static short snap_mesh_edge_verts_mixed(
{
nearest.index = vindex[v_id];
nearest2d.copy_vert_no(vindex[v_id], nearest.no, nearest2d.userdata);
elem = SCE_SELECT_VERTEX;
elem = SCE_SNAP_MODE_VERTEX;
}
}
@ -1319,7 +1319,7 @@ static short snapArmature(
{
short retval = 0;
if (snapdata->snap_to_flag == SCE_SELECT_FACE) { /* Currently only edge and vert */
if (snapdata->snap_to_flag == SCE_SNAP_MODE_FACE) { /* Currently only edge and vert */
return retval;
}
@ -1361,7 +1361,7 @@ static short snapArmature(
if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
bool has_vert_snap = false;
if (snapdata->snap_to_flag & SCE_SELECT_VERTEX) {
if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
has_vert_snap = test_projected_vert_dist(
&neasrest_precalc,
clip_planes_local, snapdata->clip_plane_len,
@ -1372,17 +1372,17 @@ static short snapArmature(
is_persp, eBone->tail, &dist_px_sq, r_loc);
if (has_vert_snap) {
retval = SCE_SELECT_VERTEX;
retval = SCE_SNAP_MODE_VERTEX;
}
}
if (!has_vert_snap && snapdata->snap_to_flag & SCE_SELECT_EDGE) {
if (!has_vert_snap && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
if (test_projected_edge_dist(
&neasrest_precalc,
clip_planes_local, snapdata->clip_plane_len,
is_persp, eBone->head, eBone->tail,
&dist_px_sq, r_loc))
{
retval = SCE_SELECT_EDGE;
retval = SCE_SNAP_MODE_EDGE;
}
}
}
@ -1398,7 +1398,7 @@ static short snapArmature(
const float *head_vec = pchan->pose_head;
const float *tail_vec = pchan->pose_tail;
if (snapdata->snap_to_flag & SCE_SELECT_VERTEX) {
if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
has_vert_snap = test_projected_vert_dist(
&neasrest_precalc,
clip_planes_local, snapdata->clip_plane_len,
@ -1409,17 +1409,17 @@ static short snapArmature(
is_persp, tail_vec, &dist_px_sq, r_loc);
if (has_vert_snap) {
retval = SCE_SELECT_VERTEX;
retval = SCE_SNAP_MODE_VERTEX;
}
}
if (!has_vert_snap && snapdata->snap_to_flag & SCE_SELECT_EDGE) {
if (!has_vert_snap && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
if (test_projected_edge_dist(
&neasrest_precalc,
clip_planes_local, snapdata->clip_plane_len,
is_persp, head_vec, tail_vec,
&dist_px_sq, r_loc))
{
retval = SCE_SELECT_EDGE;
retval = SCE_SNAP_MODE_EDGE;
}
}
}
@ -1450,7 +1450,7 @@ static short snapCurve(
bool has_snap = false;
/* only vertex snapping mode (eg control points and handles) supported for now) */
if (snapdata->snap_to_flag != SCE_SELECT_VERTEX) {
if (snapdata->snap_to_flag != SCE_SNAP_MODE_VERTEX) {
return 0;
}
@ -1489,7 +1489,7 @@ static short snapCurve(
for (Nurb *nu = (use_obedit ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
for (int u = 0; u < nu->pntsu; u++) {
if (snapdata->snap_to_flag & SCE_SELECT_VERTEX) {
if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
if (use_obedit) {
if (nu->bezt) {
/* don't snap to selected (moving) or hidden */
@ -1562,7 +1562,7 @@ static short snapCurve(
/* Does not support index yet. */
*r_index = -1;
}
return SCE_SELECT_VERTEX;
return SCE_SNAP_MODE_VERTEX;
}
return 0;
@ -1584,7 +1584,7 @@ static short snapEmpty(
}
/* for now only vertex supported */
if (snapdata->snap_to_flag & SCE_SELECT_VERTEX) {
if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
struct DistProjectedAABBPrecalc neasrest_precalc;
dist_squared_to_projected_aabb_precalc(
&neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
@ -1605,7 +1605,7 @@ static short snapEmpty(
is_persp, co, &dist_px_sq, r_loc))
{
*dist_px = sqrtf(dist_px_sq);
retval = SCE_SELECT_VERTEX;
retval = SCE_SNAP_MODE_VERTEX;
}
}
@ -1659,7 +1659,7 @@ static short snapCamera(
invert_m4_m4(orig_camera_imat, orig_camera_mat);
invert_m4_m4(imat, obmat);
if (snapdata->snap_to_flag & SCE_SELECT_VERTEX) {
if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
struct DistProjectedAABBPrecalc neasrest_precalc;
dist_squared_to_projected_aabb_precalc(
&neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
@ -1704,7 +1704,7 @@ static short snapCamera(
clip_planes_local, snapdata->clip_plane_len,
is_persp, bundle_pos, &dist_px_sq, r_loc))
{
retval = SCE_SELECT_VERTEX;
retval = SCE_SNAP_MODE_VERTEX;
}
}
}
@ -1730,9 +1730,9 @@ static short snapMesh(
/* return args */
float r_loc[3], float r_no[3], int *r_index)
{
BLI_assert(snapdata->snap_to_flag != SCE_SELECT_FACE);
BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
if ((snapdata->snap_to_flag & ~SCE_SELECT_FACE) == SCE_SELECT_EDGE) {
if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
if (me->totedge == 0) {
return 0;
}
@ -1822,7 +1822,7 @@ static short snapMesh(
treedata->edge_allocated = dummy_treedata.edge_allocated;
}
}
if (snapdata->snap_to_flag & SCE_SELECT_VERTEX) {
if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
if (sod->has_loose_vert && bvhtree[1] == NULL) {
bvhtree[1] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEVERTS, 2);
sod->has_loose_vert = bvhtree[1] != NULL;
@ -1871,7 +1871,7 @@ static short snapMesh(
.dist_sq = dist_px_sq,
};
int last_index = nearest.index;
short elem = SCE_SELECT_VERTEX;
short elem = SCE_SNAP_MODE_VERTEX;
float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
transpose_m4_m4(tobmat, obmat);
@ -1879,7 +1879,7 @@ static short snapMesh(
mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
}
if (bvhtree[1] && (snapdata->snap_to_flag & SCE_SELECT_VERTEX)) {
if (bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
/* snap to loose verts */
BLI_bvhtree_find_nearest_projected(
bvhtree[1], lpmat, snapdata->win_size, snapdata->mval,
@ -1889,7 +1889,7 @@ static short snapMesh(
last_index = nearest.index;
}
if (snapdata->snap_to_flag & SCE_SELECT_EDGE) {
if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
if (bvhtree[0]) {
/* snap to loose edges */
BLI_bvhtree_find_nearest_projected(
@ -1907,11 +1907,11 @@ static short snapMesh(
}
if (last_index != nearest.index) {
elem = SCE_SELECT_EDGE;
elem = SCE_SNAP_MODE_EDGE;
}
}
else {
BLI_assert(snapdata->snap_to_flag & SCE_SELECT_VERTEX);
BLI_assert(snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX);
if (bvhtree[0]) {
/* snap to loose edges */
BLI_bvhtree_find_nearest_projected(
@ -1961,9 +1961,9 @@ static short snapEditMesh(
/* return args */
float r_loc[3], float r_no[3], int *r_index)
{
BLI_assert(snapdata->snap_to_flag != SCE_SELECT_FACE);
BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
if ((snapdata->snap_to_flag & ~SCE_SELECT_FACE) == SCE_SELECT_EDGE) {
if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
if (em->bm->totedge == 0) {
return 0;
}
@ -1986,7 +1986,7 @@ static short snapEditMesh(
sod->sd.type = SNAP_EDIT_MESH;
}
if (snapdata->snap_to_flag & SCE_SELECT_VERTEX) {
if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
if (sod->bvh_trees[0] == NULL) {
sod->bvh_trees[0] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
}
@ -2006,7 +2006,7 @@ static short snapEditMesh(
}
}
if (snapdata->snap_to_flag & SCE_SELECT_EDGE) {
if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
if (sod->bvh_trees[1] == NULL) {
sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
}
@ -2040,7 +2040,7 @@ static short snapEditMesh(
.dist_sq = SQUARE(*dist_px),
};
int last_index = nearest.index;
short elem = SCE_SELECT_VERTEX;
short elem = SCE_SNAP_MODE_VERTEX;
float lpmat[4][4], tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
@ -2050,7 +2050,7 @@ static short snapEditMesh(
mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
}
if (treedata_vert && snapdata->snap_to_flag & SCE_SELECT_VERTEX) {
if (treedata_vert && snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
BLI_bvhtree_find_nearest_projected(
treedata_vert->tree, lpmat, snapdata->win_size, snapdata->mval,
@ -2060,7 +2060,7 @@ static short snapEditMesh(
last_index = nearest.index;
}
if (treedata_edge && snapdata->snap_to_flag & SCE_SELECT_EDGE) {
if (treedata_edge && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT);
BLI_bvhtree_find_nearest_projected(
treedata_edge->tree, lpmat, snapdata->win_size, snapdata->mval,
@ -2068,7 +2068,7 @@ static short snapEditMesh(
&nearest, cb_snap_edge, &nearest2d);
if (last_index != nearest.index) {
elem = SCE_SELECT_EDGE;
elem = SCE_SNAP_MODE_EDGE;
}
}
@ -2448,8 +2448,11 @@ static short transform_snap_context_project_view3d_mixed_impl(
float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4])
{
BLI_assert(snap_to_flag != 0);
BLI_assert((snap_to_flag & ~(1 | 2 | 4)) == 0);
BLI_assert(
(snap_to_flag & (
SCE_SNAP_MODE_VERTEX |
SCE_SNAP_MODE_EDGE |
SCE_SNAP_MODE_FACE)) != 0);
short retval = 0;
bool has_hit = false;
@ -2461,7 +2464,7 @@ static short transform_snap_context_project_view3d_mixed_impl(
const ARegion *ar = sctx->v3d_data.ar;
const RegionView3D *rv3d = ar->regiondata;
if (snap_to_flag & SCE_SELECT_FACE || params->use_occlusion_test) {
if (snap_to_flag & SCE_SNAP_MODE_FACE || params->use_occlusion_test) {
float ray_start[3], ray_normal[3];
if (!ED_view3d_win_to_ray_ex(
@ -2480,12 +2483,12 @@ static short transform_snap_context_project_view3d_mixed_impl(
&dummy_ray_depth, loc, no,
&index, &ob, obmat, NULL);
if (has_hit && (snap_to_flag & SCE_SELECT_FACE)) {
retval = SCE_SELECT_FACE;
if (has_hit && (snap_to_flag & SCE_SNAP_MODE_FACE)) {
retval = SCE_SNAP_MODE_FACE;
}
}
if (snap_to_flag & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
if (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE)) {
short elem;
float dist_px_tmp = *dist_px;
@ -2534,8 +2537,8 @@ static short transform_snap_context_project_view3d_mixed_impl(
retval = elem;
}
if ((retval == SCE_SELECT_EDGE) &&
(snapdata.snap_to_flag & SCE_SELECT_VERTEX))
if ((retval == SCE_SNAP_MODE_EDGE) &&
(snapdata.snap_to_flag & SCE_SNAP_MODE_VERTEX))
{
retval = snap_mesh_edge_verts_mixed(
sctx, &snapdata,
@ -2566,6 +2569,21 @@ static short transform_snap_context_project_view3d_mixed_impl(
return 0;
}
bool ED_transform_snap_object_project_view3d_ex(
SnapObjectContext *sctx,
const unsigned short snap_to,
const struct SnapObjectParams *params,
const float mval[2], float *dist_px,
float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4])
{
return transform_snap_context_project_view3d_mixed_impl(
sctx,
snap_to, params,
mval, dist_px,
r_loc, r_no, r_index, r_ob, r_obmat) != 0;
}
/**
* Convenience function for performing snapping.
*
@ -2578,50 +2596,6 @@ static short transform_snap_context_project_view3d_mixed_impl(
* \param r_no: hit normal (optional).
* \return Snap success
*/
bool ED_transform_snap_object_project_view3d_mixed(
SnapObjectContext *sctx,
const unsigned short snap_to_flag,
const struct SnapObjectParams *params,
const float mval_fl[2], float *dist_px,
float r_co[3], float r_no[3])
{
return transform_snap_context_project_view3d_mixed_impl(
sctx,
snap_to_flag, params,
mval_fl, dist_px,
r_co, r_no, NULL, NULL, NULL) != 0;
}
bool ED_transform_snap_object_project_view3d_ex(
SnapObjectContext *sctx,
const unsigned short snap_to,
const struct SnapObjectParams *params,
const float mval[2], float *dist_px,
float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4])
{
short snap_to_flag;
switch (snap_to) {
case SCE_SNAP_MODE_FACE:
snap_to_flag = SCE_SELECT_FACE;
break;
case SCE_SNAP_MODE_VERTEX:
snap_to_flag = SCE_SELECT_VERTEX;
break;
case SCE_SNAP_MODE_EDGE:
snap_to_flag = SCE_SELECT_EDGE;
break;
default:
return false;
}
return transform_snap_context_project_view3d_mixed_impl(
sctx,
snap_to_flag, params,
mval, dist_px,
r_loc, r_no, r_index, r_ob, r_obmat) != 0;
}
bool ED_transform_snap_object_project_view3d(
SnapObjectContext *sctx,
const unsigned short snap_to,

View File

@ -1783,16 +1783,18 @@ enum {
#define SCE_SNAP_TARGET_CENTER 1
#define SCE_SNAP_TARGET_MEDIAN 2
#define SCE_SNAP_TARGET_ACTIVE 3
/* ToolSettings.snap_mode */
#define SCE_SNAP_MODE_INCREMENT 0
#define SCE_SNAP_MODE_VERTEX 1
#define SCE_SNAP_MODE_EDGE 2
#define SCE_SNAP_MODE_FACE 3
#define SCE_SNAP_MODE_VOLUME 4
#define SCE_SNAP_MODE_NODE_X 5
#define SCE_SNAP_MODE_NODE_Y 6
#define SCE_SNAP_MODE_NODE_XY 7
#define SCE_SNAP_MODE_GRID 8
#define SCE_SNAP_MODE_VERTEX (1 << 0)
#define SCE_SNAP_MODE_EDGE (1 << 1)
#define SCE_SNAP_MODE_FACE (1 << 2)
#define SCE_SNAP_MODE_VOLUME (1 << 3)
#define SCE_SNAP_MODE_INCREMENT (1 << 4)
/* ToolSettings.snap_node_mode */
#define SCE_SNAP_MODE_GRID (1 << 5)
#define SCE_SNAP_MODE_NODE_X (1 << 6)
#define SCE_SNAP_MODE_NODE_Y (1 << 7)
/* ToolSettings.selectmode */
#define SCE_SELECT_VERTEX 1 /* for mesh */

View File

@ -175,10 +175,11 @@ const EnumPropertyItem rna_enum_snap_element_items[] = {
};
const EnumPropertyItem rna_enum_snap_node_element_items[] = {
{SCE_SNAP_MODE_GRID, "GRID", ICON_SNAP_GRID, "Grid", "Snap to grid"},
{SCE_SNAP_MODE_NODE_X, "NODE_X", ICON_SNAP_EDGE, "Node X", "Snap to left/right node border"},
{SCE_SNAP_MODE_NODE_Y, "NODE_Y", ICON_SNAP_EDGE, "Node Y", "Snap to top/bottom node border"},
{SCE_SNAP_MODE_NODE_XY, "NODE_XY", ICON_SNAP_EDGE, "Node X / Y", "Snap to any node border"},
{SCE_SNAP_MODE_GRID , "GRID" , ICON_SNAP_GRID, "Grid", "Snap to grid"},
{SCE_SNAP_MODE_NODE_X, "NODE_X" , ICON_SNAP_EDGE, "Node X", "Snap to left/right node border"},
{SCE_SNAP_MODE_NODE_Y, "NODE_Y" , ICON_SNAP_EDGE, "Node Y", "Snap to top/bottom node border"},
{SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y,
"NODE_XY", ICON_SNAP_EDGE, "Node X / Y", "Snap to any node border"},
{0, NULL, 0, NULL, NULL}
};
@ -2644,22 +2645,23 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_SNAP_GRID, 0);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
prop = RNA_def_property(srna, "snap_element", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "snap_mode");
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);
RNA_def_property_flag(prop, PROP_ENUM_FLAG);
RNA_def_property_ui_text(prop, "Snap Element", "Type of element to snap to");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
/* node editor uses own set of snap modes */
prop = RNA_def_property(srna, "snap_node_element", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "snap_node_mode");
RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_node_mode");
RNA_def_property_enum_items(prop, rna_enum_snap_node_element_items);
RNA_def_property_ui_text(prop, "Snap Node Element", "Type of element to snap to");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
/* image editor uses own set of snap modes */
prop = RNA_def_property(srna, "snap_uv_element", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "snap_uv_mode");
RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_uv_mode");
RNA_def_property_enum_items(prop, snap_uv_element_items);
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 */