Transform: Add option to exclude back facing geometry from snapping
Add new `Backface Culling` option to the snapping properties. This option has nothing to do with the view3d display or the workbench `Backface Culling` option. Limitation: - In edit mode, this option only affects snap to faces. Maniphest Tasks: T71217 Differential Revision: https://developer.blender.org/D6155
This commit is contained in:
parent
3c32c5c2dd
commit
44d67b6dc8
Notes:
blender-bot
2023-02-14 05:41:57 +01:00
Referenced by issue #71217, Add option to exclude back facing geometry from snapping
|
@ -6082,6 +6082,8 @@ class VIEW3D_PT_snapping(Panel):
|
|||
row = col.row(align=True)
|
||||
row.prop(tool_settings, "snap_target", expand=True)
|
||||
|
||||
col.prop(tool_settings, "use_snap_backface_culling")
|
||||
|
||||
if obj:
|
||||
if object_mode == 'EDIT':
|
||||
col.prop(tool_settings, "use_snap_self")
|
||||
|
|
|
@ -68,6 +68,8 @@ struct SnapObjectParams {
|
|||
unsigned int use_object_edit_cage : 1;
|
||||
/* snap to the closest element, use when using more than one snap type */
|
||||
unsigned int use_occlusion_test : 1;
|
||||
/* exclude back facing geometry from snapping */
|
||||
unsigned int use_backface_culling : 1;
|
||||
};
|
||||
|
||||
typedef struct SnapObjectContext SnapObjectContext;
|
||||
|
|
|
@ -379,6 +379,8 @@ void applyProject(TransInfo *t)
|
|||
.snap_select = t->tsnap.modeSelect,
|
||||
.use_object_edit_cage = (t->flag & T_EDIT) != 0,
|
||||
.use_occlusion_test = false,
|
||||
.use_backface_culling = (t->scene->toolsettings->snap_flag &
|
||||
SCE_SNAP_BACKFACE_CULLING) != 0,
|
||||
},
|
||||
mval_fl,
|
||||
NULL,
|
||||
|
@ -1364,6 +1366,8 @@ short snapObjectsTransform(
|
|||
.snap_select = t->tsnap.modeSelect,
|
||||
.use_object_edit_cage = (t->flag & T_EDIT) != 0,
|
||||
.use_occlusion_test = t->scene->toolsettings->snap_mode != SCE_SNAP_MODE_FACE,
|
||||
.use_backface_culling = (t->scene->toolsettings->snap_flag &
|
||||
SCE_SNAP_BACKFACE_CULLING) != 0,
|
||||
},
|
||||
mval,
|
||||
t->tsnap.snapTarget,
|
||||
|
|
|
@ -201,8 +201,12 @@ static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext
|
|||
return *sod_p;
|
||||
}
|
||||
|
||||
typedef void (*IterSnapObjsCallback)(
|
||||
SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data);
|
||||
typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx,
|
||||
bool is_obedit,
|
||||
bool use_backface_culling,
|
||||
Object *ob,
|
||||
float obmat[4][4],
|
||||
void *data);
|
||||
|
||||
/**
|
||||
* Walks through all objects in the scene to create the list of objects to snap.
|
||||
|
@ -219,6 +223,7 @@ static void iter_snap_objects(SnapObjectContext *sctx,
|
|||
const View3D *v3d = sctx->v3d_data.v3d;
|
||||
const eSnapSelect snap_select = params->snap_select;
|
||||
const bool use_object_edit_cage = params->use_object_edit_cage;
|
||||
const bool use_backface_culling = params->use_backface_culling;
|
||||
|
||||
Base *base_act = view_layer->basact;
|
||||
for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
|
||||
|
@ -250,12 +255,14 @@ static void iter_snap_objects(SnapObjectContext *sctx,
|
|||
DupliObject *dupli_ob;
|
||||
ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj_eval);
|
||||
for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
|
||||
sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data);
|
||||
sob_callback(
|
||||
sctx, use_object_edit_cage, use_backface_culling, dupli_ob->ob, dupli_ob->mat, data);
|
||||
}
|
||||
free_object_duplilist(lb);
|
||||
}
|
||||
|
||||
sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data);
|
||||
sob_callback(
|
||||
sctx, use_object_edit_cage, use_backface_culling, obj_eval, obj_eval->obmat, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,6 +357,70 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH
|
|||
}
|
||||
}
|
||||
|
||||
static bool raycast_tri_backface_culling_test(
|
||||
const float dir[3], const float v0[3], const float v1[3], const float v2[3], float no[3])
|
||||
{
|
||||
cross_tri_v3(no, v0, v1, v2);
|
||||
return dot_v3v3(no, dir) < 0.0f;
|
||||
}
|
||||
|
||||
/* Callback to raycast with backface culling (Mesh). */
|
||||
static void mesh_looptri_raycast_backface_culling_cb(void *userdata,
|
||||
int index,
|
||||
const BVHTreeRay *ray,
|
||||
BVHTreeRayHit *hit)
|
||||
{
|
||||
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
|
||||
const MVert *vert = data->vert;
|
||||
const MLoopTri *lt = &data->looptri[index];
|
||||
const float *vtri_co[3] = {
|
||||
vert[data->loop[lt->tri[0]].v].co,
|
||||
vert[data->loop[lt->tri[1]].v].co,
|
||||
vert[data->loop[lt->tri[2]].v].co,
|
||||
};
|
||||
float dist = bvhtree_ray_tri_intersection(ray, hit->dist, UNPACK3(vtri_co));
|
||||
|
||||
if (dist >= 0 && dist < hit->dist) {
|
||||
float no[3];
|
||||
if (raycast_tri_backface_culling_test(ray->direction, UNPACK3(vtri_co), no)) {
|
||||
hit->index = index;
|
||||
hit->dist = dist;
|
||||
madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
|
||||
normalize_v3_v3(hit->no, no);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Callback to raycast with backface culling (EditMesh). */
|
||||
static void editmesh_looptri_raycast_backface_culling_cb(void *userdata,
|
||||
int index,
|
||||
const BVHTreeRay *ray,
|
||||
BVHTreeRayHit *hit)
|
||||
{
|
||||
const BVHTreeFromEditMesh *data = (BVHTreeFromEditMesh *)userdata;
|
||||
BMEditMesh *em = data->em;
|
||||
const BMLoop **ltri = (const BMLoop **)em->looptris[index];
|
||||
|
||||
const float *t0, *t1, *t2;
|
||||
t0 = ltri[0]->v->co;
|
||||
t1 = ltri[1]->v->co;
|
||||
t2 = ltri[2]->v->co;
|
||||
|
||||
{
|
||||
float dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
|
||||
|
||||
if (dist >= 0 && dist < hit->dist) {
|
||||
float no[3];
|
||||
if (raycast_tri_backface_culling_test(ray->direction, t0, t1, t2, no)) {
|
||||
hit->index = index;
|
||||
hit->dist = dist;
|
||||
madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
|
||||
normalize_v3_v3(hit->no, no);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool raycastMesh(SnapObjectContext *sctx,
|
||||
const float ray_start[3],
|
||||
const float ray_dir[3],
|
||||
|
@ -358,6 +429,7 @@ static bool raycastMesh(SnapObjectContext *sctx,
|
|||
const float obmat[4][4],
|
||||
const unsigned int ob_index,
|
||||
bool use_hide,
|
||||
bool use_backface_culling,
|
||||
/* read/write args */
|
||||
float *ray_depth,
|
||||
/* return args */
|
||||
|
@ -494,7 +566,8 @@ static bool raycastMesh(SnapObjectContext *sctx,
|
|||
ray_normal_local,
|
||||
0.0f,
|
||||
&hit,
|
||||
treedata->raycast_callback,
|
||||
use_backface_culling ? mesh_looptri_raycast_backface_culling_cb :
|
||||
treedata->raycast_callback,
|
||||
treedata) != -1) {
|
||||
hit.dist += len_diff;
|
||||
hit.dist /= local_scale;
|
||||
|
@ -530,6 +603,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
|
|||
BMEditMesh *em,
|
||||
const float obmat[4][4],
|
||||
const unsigned int ob_index,
|
||||
bool use_backface_culling,
|
||||
/* read/write args */
|
||||
float *ray_depth,
|
||||
/* return args */
|
||||
|
@ -670,7 +744,8 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
|
|||
ray_normal_local,
|
||||
0.0f,
|
||||
&hit,
|
||||
treedata->raycast_callback,
|
||||
use_backface_culling ? editmesh_looptri_raycast_backface_culling_cb :
|
||||
treedata->raycast_callback,
|
||||
treedata) != -1) {
|
||||
hit.dist += len_diff;
|
||||
hit.dist /= local_scale;
|
||||
|
@ -715,6 +790,7 @@ static bool raycastObj(SnapObjectContext *sctx,
|
|||
const unsigned int ob_index,
|
||||
bool use_obedit,
|
||||
bool use_occlusion_test,
|
||||
bool use_backface_culling,
|
||||
/* read/write args */
|
||||
float *ray_depth,
|
||||
/* return args */
|
||||
|
@ -753,6 +829,7 @@ static bool raycastObj(SnapObjectContext *sctx,
|
|||
em,
|
||||
obmat,
|
||||
ob_index,
|
||||
use_backface_culling,
|
||||
ray_depth,
|
||||
r_loc,
|
||||
r_no,
|
||||
|
@ -773,6 +850,7 @@ static bool raycastObj(SnapObjectContext *sctx,
|
|||
obmat,
|
||||
ob_index,
|
||||
use_hide,
|
||||
use_backface_culling,
|
||||
ray_depth,
|
||||
r_loc,
|
||||
r_no,
|
||||
|
@ -792,6 +870,7 @@ static bool raycastObj(SnapObjectContext *sctx,
|
|||
obmat,
|
||||
ob_index,
|
||||
false,
|
||||
use_backface_culling,
|
||||
ray_depth,
|
||||
r_loc,
|
||||
r_no,
|
||||
|
@ -832,8 +911,12 @@ struct RaycastObjUserData {
|
|||
bool ret;
|
||||
};
|
||||
|
||||
static void raycast_obj_cb(
|
||||
SnapObjectContext *sctx, bool use_obedit, Object *ob, float obmat[4][4], void *data)
|
||||
static void raycast_obj_cb(SnapObjectContext *sctx,
|
||||
bool use_obedit,
|
||||
bool use_backface_culling,
|
||||
Object *ob,
|
||||
float obmat[4][4],
|
||||
void *data)
|
||||
{
|
||||
struct RaycastObjUserData *dt = data;
|
||||
|
||||
|
@ -845,6 +928,7 @@ static void raycast_obj_cb(
|
|||
dt->ob_index++,
|
||||
use_obedit,
|
||||
dt->use_occlusion_test,
|
||||
use_backface_culling,
|
||||
dt->ray_depth,
|
||||
dt->r_loc,
|
||||
dt->r_no,
|
||||
|
@ -1088,8 +1172,6 @@ typedef void (*Nearest2DGetTriEdgesCallback)(const int index, int e_index[3], vo
|
|||
typedef void (*Nearest2DCopyVertNoCallback)(const int index, float r_no[3], void *data);
|
||||
|
||||
typedef struct Nearest2dUserData {
|
||||
bool is_persp;
|
||||
|
||||
void *userdata;
|
||||
Nearest2DGetVertCoCallback get_vert_co;
|
||||
Nearest2DGetEdgeVertsCallback get_edge_verts_index;
|
||||
|
@ -1097,6 +1179,8 @@ typedef struct Nearest2dUserData {
|
|||
Nearest2DGetTriEdgesCallback get_tri_edges_index;
|
||||
Nearest2DCopyVertNoCallback copy_vert_no;
|
||||
|
||||
bool is_persp;
|
||||
bool use_backface_culling;
|
||||
} Nearest2dUserData;
|
||||
|
||||
static void cb_snap_vert(void *userdata,
|
||||
|
@ -1181,6 +1265,20 @@ static void cb_snap_tri_edges(void *userdata,
|
|||
{
|
||||
struct Nearest2dUserData *data = userdata;
|
||||
|
||||
if (data->use_backface_culling) {
|
||||
int vindex[3];
|
||||
data->get_tri_verts_index(index, vindex, data->userdata);
|
||||
|
||||
const float *t0, *t1, *t2;
|
||||
data->get_vert_co(vindex[0], &t0, data->userdata);
|
||||
data->get_vert_co(vindex[1], &t1, data->userdata);
|
||||
data->get_vert_co(vindex[2], &t2, data->userdata);
|
||||
float dummy[3];
|
||||
if (raycast_tri_backface_culling_test(precalc->ray_direction, t0, t1, t2, dummy)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int eindex[3];
|
||||
data->get_tri_edges_index(index, eindex, data->userdata);
|
||||
for (int i = 3; i--;) {
|
||||
|
@ -1204,6 +1302,18 @@ static void cb_snap_tri_verts(void *userdata,
|
|||
|
||||
int vindex[3];
|
||||
data->get_tri_verts_index(index, vindex, data->userdata);
|
||||
|
||||
if (data->use_backface_culling) {
|
||||
const float *t0, *t1, *t2;
|
||||
data->get_vert_co(vindex[0], &t0, data->userdata);
|
||||
data->get_vert_co(vindex[1], &t1, data->userdata);
|
||||
data->get_vert_co(vindex[2], &t2, data->userdata);
|
||||
float dummy[3];
|
||||
if (raycast_tri_backface_culling_test(precalc->ray_direction, t0, t1, t2, dummy)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 3; i--;) {
|
||||
if (vindex[i] == nearest->index) {
|
||||
continue;
|
||||
|
@ -1222,6 +1332,7 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
|
|||
SnapData *snapdata,
|
||||
Object *ob,
|
||||
const float obmat[4][4],
|
||||
bool use_backface_culling,
|
||||
/* read/write args */
|
||||
float *dist_px,
|
||||
/* return args */
|
||||
|
@ -1246,6 +1357,7 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
|
|||
|
||||
Nearest2dUserData nearest2d = {
|
||||
.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
|
||||
.use_backface_culling = use_backface_culling,
|
||||
};
|
||||
|
||||
BVHTreeNearest nearest = {
|
||||
|
@ -1366,6 +1478,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
|
|||
const float obmat[4][4],
|
||||
float original_dist_px,
|
||||
const float prev_co[3],
|
||||
bool use_backface_culling,
|
||||
/* read/write args */
|
||||
float *dist_px,
|
||||
/* return args */
|
||||
|
@ -1392,6 +1505,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
|
|||
Nearest2dUserData nearest2d;
|
||||
{
|
||||
nearest2d.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
|
||||
nearest2d.use_backface_culling = use_backface_culling;
|
||||
if (sod->type == SNAP_MESH) {
|
||||
nearest2d.userdata = &((SnapObjectData_Mesh *)sod)->treedata;
|
||||
nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
|
||||
|
@ -1995,6 +2109,7 @@ static short snapMesh(SnapObjectContext *sctx,
|
|||
Object *ob,
|
||||
Mesh *me,
|
||||
const float obmat[4][4],
|
||||
bool use_backface_culling,
|
||||
/* read/write args */
|
||||
float *dist_px,
|
||||
/* return args */
|
||||
|
@ -2107,13 +2222,14 @@ static short snapMesh(SnapObjectContext *sctx,
|
|||
}
|
||||
|
||||
Nearest2dUserData nearest2d = {
|
||||
.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
|
||||
.userdata = treedata,
|
||||
.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get,
|
||||
.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get,
|
||||
.get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get,
|
||||
.get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get,
|
||||
.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy,
|
||||
.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
|
||||
.use_backface_culling = use_backface_culling,
|
||||
};
|
||||
|
||||
BVHTreeNearest nearest = {
|
||||
|
@ -2233,6 +2349,7 @@ static short snapEditMesh(SnapObjectContext *sctx,
|
|||
Object *ob,
|
||||
BMEditMesh *em,
|
||||
const float obmat[4][4],
|
||||
bool use_backface_culling,
|
||||
/* read/write args */
|
||||
float *dist_px,
|
||||
/* return args */
|
||||
|
@ -2346,11 +2463,12 @@ static short snapEditMesh(SnapObjectContext *sctx,
|
|||
}
|
||||
|
||||
Nearest2dUserData nearest2d = {
|
||||
.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
|
||||
.userdata = em,
|
||||
.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get,
|
||||
.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get,
|
||||
.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy,
|
||||
.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
|
||||
.use_backface_culling = use_backface_culling,
|
||||
};
|
||||
|
||||
BVHTreeNearest nearest = {
|
||||
|
@ -2436,6 +2554,7 @@ static short snapObject(SnapObjectContext *sctx,
|
|||
Object *ob,
|
||||
float obmat[4][4],
|
||||
bool use_obedit,
|
||||
bool use_backface_culling,
|
||||
/* read/write args */
|
||||
float *dist_px,
|
||||
/* return args */
|
||||
|
@ -2453,7 +2572,8 @@ static short snapObject(SnapObjectContext *sctx,
|
|||
if (BKE_object_is_in_editmode(ob)) {
|
||||
BMEditMesh *em = BKE_editmesh_from_object(ob);
|
||||
if (use_obedit) {
|
||||
retval = snapEditMesh(sctx, snapdata, ob, em, obmat, dist_px, r_loc, r_no, r_index);
|
||||
retval = snapEditMesh(
|
||||
sctx, snapdata, ob, em, obmat, use_backface_culling, dist_px, r_loc, r_no, r_index);
|
||||
break;
|
||||
}
|
||||
else if (em->mesh_eval_final) {
|
||||
|
@ -2465,7 +2585,8 @@ static short snapObject(SnapObjectContext *sctx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
retval = snapMesh(sctx, snapdata, ob, me, obmat, dist_px, r_loc, r_no, r_index);
|
||||
retval = snapMesh(
|
||||
sctx, snapdata, ob, me, obmat, use_backface_culling, dist_px, r_loc, r_no, r_index);
|
||||
break;
|
||||
}
|
||||
case OB_ARMATURE:
|
||||
|
@ -2477,8 +2598,16 @@ static short snapObject(SnapObjectContext *sctx,
|
|||
case OB_SURF:
|
||||
case OB_FONT: {
|
||||
if (ob->runtime.mesh_eval) {
|
||||
retval |= snapMesh(
|
||||
sctx, snapdata, ob, ob->runtime.mesh_eval, obmat, dist_px, r_loc, r_no, r_index);
|
||||
retval |= snapMesh(sctx,
|
||||
snapdata,
|
||||
ob,
|
||||
ob->runtime.mesh_eval,
|
||||
obmat,
|
||||
use_backface_culling,
|
||||
dist_px,
|
||||
r_loc,
|
||||
r_no,
|
||||
r_index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2519,8 +2648,12 @@ struct SnapObjUserData {
|
|||
short ret;
|
||||
};
|
||||
|
||||
static void sanp_obj_cb(
|
||||
SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data)
|
||||
static void sanp_obj_cb(SnapObjectContext *sctx,
|
||||
bool is_obedit,
|
||||
bool use_backface_culling,
|
||||
Object *ob,
|
||||
float obmat[4][4],
|
||||
void *data)
|
||||
{
|
||||
struct SnapObjUserData *dt = data;
|
||||
|
||||
|
@ -2529,6 +2662,7 @@ static void sanp_obj_cb(
|
|||
ob,
|
||||
obmat,
|
||||
is_obedit,
|
||||
use_backface_culling,
|
||||
/* read/write args */
|
||||
dt->dist_px,
|
||||
/* return args */
|
||||
|
@ -2881,7 +3015,8 @@ static short transform_snap_context_project_view3d_mixed_impl(
|
|||
new_clipplane[3] += 0.01f;
|
||||
|
||||
/* Try to snap only to the polygon. */
|
||||
elem_test = snap_mesh_polygon(sctx, &snapdata, ob, obmat, &dist_px_tmp, loc, no, &index);
|
||||
elem_test = snap_mesh_polygon(
|
||||
sctx, &snapdata, ob, obmat, params->use_backface_culling, &dist_px_tmp, loc, no, &index);
|
||||
if (elem_test) {
|
||||
elem = elem_test;
|
||||
}
|
||||
|
@ -2904,8 +3039,17 @@ static short transform_snap_context_project_view3d_mixed_impl(
|
|||
(snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE_MIDPOINT |
|
||||
SCE_SNAP_MODE_EDGE_PERPENDICULAR))) {
|
||||
snapdata.snap_to_flag = snap_to_flag;
|
||||
elem = snap_mesh_edge_verts_mixed(
|
||||
sctx, &snapdata, ob, obmat, *dist_px, prev_co, &dist_px_tmp, loc, no, &index);
|
||||
elem = snap_mesh_edge_verts_mixed(sctx,
|
||||
&snapdata,
|
||||
ob,
|
||||
obmat,
|
||||
*dist_px,
|
||||
prev_co,
|
||||
params->use_backface_culling,
|
||||
&dist_px_tmp,
|
||||
loc,
|
||||
no,
|
||||
&index);
|
||||
}
|
||||
|
||||
if (elem & snap_to_flag) {
|
||||
|
|
|
@ -2035,6 +2035,7 @@ enum {
|
|||
#define SCE_SNAP_PROJECT (1 << 3)
|
||||
#define SCE_SNAP_NO_SELF (1 << 4)
|
||||
#define SCE_SNAP_ABS_GRID (1 << 5)
|
||||
#define SCE_SNAP_BACKFACE_CULLING (1 << 6)
|
||||
|
||||
/* ToolSettings.snap_target */
|
||||
#define SCE_SNAP_TARGET_CLOSEST 0
|
||||
|
|
|
@ -3035,6 +3035,11 @@ static void rna_def_tool_settings(BlenderRNA *brna)
|
|||
"Project individual elements on the surface of other objects");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
|
||||
|
||||
prop = RNA_def_property(srna, "use_snap_backface_culling", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_BACKFACE_CULLING);
|
||||
RNA_def_property_ui_text(prop, "Backface Culling", "Exclude back facing geometry from snapping");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
|
||||
|
||||
prop = RNA_def_property(srna, "use_snap_self", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "snap_flag", SCE_SNAP_NO_SELF);
|
||||
RNA_def_property_ui_text(prop, "Project onto Self", "Snap onto itself (Edit Mode Only)");
|
||||
|
|
Loading…
Reference in New Issue