Transform Snap: initial snap context refactor
This introduces a snap-context that can be re-used for casting rays into the scene (by operators such as walk-mode, ruler and transform code). This can be used to cache data between calls too.
This commit is contained in:
parent
8dcdde52b1
commit
19e5540ff7
|
@ -1086,9 +1086,23 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S
|
|||
mval[1] = dd->mval[1];
|
||||
|
||||
/* try to snap to closer object */
|
||||
found = snapObjectsContext(
|
||||
C, mval, SNAP_NOT_SELECTED,
|
||||
vec, no, &dist_px);
|
||||
{
|
||||
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
|
||||
CTX_data_main(C), CTX_data_scene(C), 0,
|
||||
CTX_wm_region(C), CTX_wm_view3d(C));
|
||||
|
||||
found = ED_transform_snap_object_project_view3d_mixed(
|
||||
snap_context,
|
||||
&(const struct SnapObjectParams){
|
||||
.snap_select = SNAP_NOT_SELECTED,
|
||||
.snap_to_flag = SCE_SELECT_FACE,
|
||||
},
|
||||
mval, &dist_px, true,
|
||||
vec, no);
|
||||
|
||||
ED_transform_snap_object_context_destroy(snap_context);
|
||||
}
|
||||
|
||||
if (found == 1) {
|
||||
pt->type = dd->type;
|
||||
pt->mode = PT_SNAP;
|
||||
|
|
|
@ -4993,11 +4993,22 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
|
||||
if (use_proj) {
|
||||
const float mval[2] = {UNPACK2(event->mval)};
|
||||
float no_dummy[3];
|
||||
float dist_px_dummy;
|
||||
snapObjectsContext(
|
||||
C, mval, SNAP_NOT_OBEDIT,
|
||||
location, no_dummy, &dist_px_dummy);
|
||||
|
||||
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
|
||||
CTX_data_main(C), vc.scene, 0,
|
||||
vc.ar, vc.v3d);
|
||||
|
||||
ED_transform_snap_object_project_view3d_mixed(
|
||||
snap_context,
|
||||
&(const struct SnapObjectParams){
|
||||
.snap_select = SNAP_NOT_OBEDIT,
|
||||
.snap_to_flag = SCE_SELECT_FACE,
|
||||
},
|
||||
mval, NULL, true,
|
||||
location, NULL);
|
||||
|
||||
|
||||
ED_transform_snap_object_context_destroy(snap_context);
|
||||
}
|
||||
|
||||
if ((cu->flag & CU_3D) == 0) {
|
||||
|
|
|
@ -43,6 +43,8 @@ struct wmEvent;
|
|||
struct wmKeyConfig;
|
||||
struct wmKeyMap;
|
||||
struct wmOperatorType;
|
||||
struct Main;
|
||||
struct SnapObjectContext;
|
||||
|
||||
void transform_keymap_for_space(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap, int spaceid);
|
||||
void transform_operatortypes(void);
|
||||
|
@ -187,27 +189,9 @@ bool peelObjectsContext(
|
|||
struct ListBase *r_depth_peels);
|
||||
bool snapObjectsTransform(
|
||||
struct TransInfo *t, const float mval[2], SnapSelect snap_select,
|
||||
float *dist_px,
|
||||
/* return args */
|
||||
float r_loc[3], float r_no[3], float *r_dist_px);
|
||||
bool snapObjectsContext(
|
||||
struct bContext *C, const float mval[2], SnapSelect snap_select,
|
||||
/* return args */
|
||||
float r_loc[3], float r_no[3], float *r_dist_px);
|
||||
/* taks args for all settings */
|
||||
bool snapObjectsEx(
|
||||
struct Scene *scene, struct View3D *v3d, struct ARegion *ar, struct Base *base_act, struct Object *obedit,
|
||||
const float mval[2], SnapSelect snap_select, const short snap_mode,
|
||||
float *ray_depth,
|
||||
/* return args */
|
||||
float r_loc[3], float r_no[3], float *r_dist_px);
|
||||
bool snapObjectsRayEx(
|
||||
struct Scene *scene, struct View3D *v3d, struct ARegion *ar, struct Base *base_act, struct Object *obedit,
|
||||
const float mval[2], SnapSelect snap_select, const short snap_mode,
|
||||
const float ray_start[3], const float ray_normal[3], float *ray_depth,
|
||||
/* return args */
|
||||
float r_loc[3], float r_no[3], float *r_dist_px, int *r_index,
|
||||
struct Object **r_ob, float r_obmat[4][4]);
|
||||
|
||||
float r_loc[3], float r_no[3]);
|
||||
bool snapNodesTransform(
|
||||
struct TransInfo *t, const int mval[2], SnapSelect snap_select,
|
||||
/* return args */
|
||||
|
@ -217,4 +201,67 @@ bool snapNodesContext(
|
|||
/* return args */
|
||||
float r_loc[2], float *r_dist_px, char *r_node_border);
|
||||
|
||||
|
||||
/* transform_snap_object.c */
|
||||
|
||||
/* ED_transform_snap_object_*** API */
|
||||
struct SnapObjectParams {
|
||||
SnapSelect snap_select;
|
||||
union {
|
||||
unsigned int snap_to : 4;
|
||||
/* snap_target_flag: Snap to vert/edge/face. */
|
||||
unsigned int snap_to_flag : 4;
|
||||
};
|
||||
/* use editmode cage */
|
||||
unsigned int use_object_edit : 1;
|
||||
/* special context sensitive handling for the active object */
|
||||
unsigned int use_object_active : 1;
|
||||
};
|
||||
|
||||
enum {
|
||||
SNAP_OBJECT_USE_CACHE = (1 << 0),
|
||||
};
|
||||
|
||||
typedef struct SnapObjectContext SnapObjectContext;
|
||||
SnapObjectContext *ED_transform_snap_object_context_create(
|
||||
struct Main *bmain, struct Scene *scene, int flag);
|
||||
SnapObjectContext *ED_transform_snap_object_context_create_view3d(
|
||||
struct Main *bmain, struct Scene *scene, int flag,
|
||||
/* extra args for view3d */
|
||||
struct ARegion *ar, struct View3D *v3d);
|
||||
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx);
|
||||
|
||||
bool ED_transform_snap_object_project_ray_ex(
|
||||
struct SnapObjectContext *sctx,
|
||||
const struct SnapObjectParams *params,
|
||||
const float ray_start[3], const float ray_normal[3], float *ray_depth,
|
||||
/* return args */
|
||||
float r_loc[3], float r_no[3], int *r_index,
|
||||
struct Object **r_ob, float r_obmat[4][4]);
|
||||
bool ED_transform_snap_object_project_ray(
|
||||
SnapObjectContext *sctx,
|
||||
const float ray_origin[3], const float ray_direction[3], float *ray_dist,
|
||||
float r_co[3], float r_no[3]);
|
||||
|
||||
bool ED_transform_snap_object_project_view3d_ex(
|
||||
struct SnapObjectContext *sctx,
|
||||
const struct SnapObjectParams *params,
|
||||
const float mval[2], float *dist_px,
|
||||
float *ray_depth,
|
||||
float r_loc[3], float r_no[3], int *r_index);
|
||||
bool ED_transform_snap_object_project_view3d(
|
||||
struct SnapObjectContext *sctx,
|
||||
const struct SnapObjectParams *params,
|
||||
const float mval[2], float *dist_px,
|
||||
float *ray_depth,
|
||||
/* return args */
|
||||
float r_loc[3], float r_no[3]);
|
||||
bool ED_transform_snap_object_project_view3d_mixed(
|
||||
SnapObjectContext *sctx,
|
||||
const struct SnapObjectParams *params,
|
||||
const float mval_fl[2], float *dist_px,
|
||||
bool use_depth,
|
||||
float r_co[3], float r_no[3]);
|
||||
|
||||
|
||||
#endif /* __ED_TRANSFORM_H__ */
|
||||
|
|
|
@ -396,18 +396,6 @@ void ED_view3d_operator_properties_viewmat_set(struct bContext *C, struct wmOper
|
|||
void ED_view3d_operator_properties_viewmat_get(struct wmOperator *op, int *winx, int *winy, float persmat[4][4]);
|
||||
#endif
|
||||
|
||||
bool ED_view3d_snap_from_region(
|
||||
struct Scene *scene, struct View3D *v3d, struct ARegion *ar,
|
||||
const float mval[2], float dist_px,
|
||||
bool use_depth, bool use_obedit,
|
||||
bool use_vert, bool use_edge, bool use_face,
|
||||
float r_co[3], float r_no[3]);
|
||||
|
||||
bool ED_view3d_snap_from_ray(
|
||||
struct Scene *scene,
|
||||
const float ray_start[3], const float ray_normal[3],
|
||||
float r_co[3]);
|
||||
|
||||
/* render */
|
||||
void ED_view3d_stop_render_preview(struct wmWindowManager *wm, struct ARegion *ar);
|
||||
void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View3D *v3d, struct ScrArea *sa);
|
||||
|
|
|
@ -301,20 +301,30 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
|
|||
|
||||
ED_view3d_init_mats_rv3d(obedit, ar->regiondata);
|
||||
|
||||
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
|
||||
CTX_data_main(C), CTX_data_scene(C), SNAP_OBJECT_USE_CACHE,
|
||||
ar, CTX_wm_view3d(C));
|
||||
|
||||
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
|
||||
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
|
||||
float mval[2], co_proj[3], no_dummy[3];
|
||||
float dist_px_dummy;
|
||||
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 (snapObjectsContext(
|
||||
C, mval, SNAP_NOT_OBEDIT,
|
||||
co_proj, no_dummy, &dist_px_dummy))
|
||||
if (ED_transform_snap_object_project_view3d_mixed(
|
||||
snap_context,
|
||||
&(const struct SnapObjectParams){
|
||||
.snap_select = SNAP_NOT_OBEDIT,
|
||||
.snap_to_flag = SCE_SELECT_FACE,
|
||||
},
|
||||
mval, NULL, true,
|
||||
co_proj, NULL))
|
||||
{
|
||||
mul_v3_m4v3(eve->co, obedit->imat, co_proj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ED_transform_snap_object_context_destroy(snap_context);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5171,85 +5171,3 @@ void ED_view3D_lock_clear(View3D *v3d)
|
|||
v3d->ob_centre_cursor = false;
|
||||
v3d->flag2 &= ~V3D_LOCK_CAMERA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function for snap ray-casting.
|
||||
*
|
||||
* Given a ray, cast it into the scene (snapping to faces).
|
||||
*
|
||||
* \return Snap success
|
||||
*/
|
||||
bool ED_view3d_snap_from_ray(
|
||||
Scene *scene,
|
||||
const float ray_start[3], const float ray_normal[3],
|
||||
float r_co[3])
|
||||
{
|
||||
float r_no_dummy[3];
|
||||
float ray_dist = BVH_RAYCAST_DIST_MAX;
|
||||
bool ret;
|
||||
|
||||
struct Object *obedit = scene->obedit;
|
||||
|
||||
/* try snap edge, then face if it fails */
|
||||
ret = snapObjectsRayEx(
|
||||
scene, NULL, NULL, NULL, obedit,
|
||||
NULL, SNAP_ALL, SCE_SNAP_MODE_FACE,
|
||||
ray_start, ray_normal, &ray_dist,
|
||||
r_co, r_no_dummy, NULL, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function for performing snapping.
|
||||
*
|
||||
* Given a 2D region value, snap to vert/edge/face.
|
||||
*
|
||||
* \param mval: Screenspace coordinate.
|
||||
* \param dist_px: Maximum distance to snap (in pixels).
|
||||
* \param use_depth: Snap to the closest element, use when using more than one snap type.
|
||||
* \param use_obedit: Use editmode cage.
|
||||
* \param use_vert: Snap to verts.
|
||||
* \param use_edge: Snap to edges.
|
||||
* \param use_face: Snap to faces.
|
||||
* \param r_co: hit location.
|
||||
* \param r_no: hit normal (optional).
|
||||
* \return Snap success
|
||||
*/
|
||||
bool ED_view3d_snap_from_region(
|
||||
Scene *scene, View3D *v3d, ARegion *ar,
|
||||
const float mval[2], float dist_px,
|
||||
bool use_depth, bool use_obedit,
|
||||
bool use_vert, bool use_edge, bool use_face,
|
||||
float r_co[3], float r_no[3])
|
||||
{
|
||||
float r_no_dummy[3];
|
||||
float ray_dist = BVH_RAYCAST_DIST_MAX;
|
||||
bool is_hit = false;
|
||||
float *r_no_ptr = r_no ? r_no : r_no_dummy;
|
||||
|
||||
struct Object *obedit = use_obedit ? scene->obedit : NULL;
|
||||
const int elem_type[3] = {SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE, SCE_SNAP_MODE_FACE};
|
||||
const bool elem_test[3] = {use_vert, use_edge, use_face};
|
||||
|
||||
BLI_assert(use_vert || use_edge || use_face);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (elem_test[i] && (is_hit == false || use_depth)) {
|
||||
if (use_depth == false) {
|
||||
ray_dist = BVH_RAYCAST_DIST_MAX;
|
||||
}
|
||||
if (snapObjectsEx(
|
||||
scene, v3d, ar, NULL, obedit,
|
||||
mval, SNAP_ALL, elem_type[i],
|
||||
&ray_dist,
|
||||
r_co, r_no_ptr, &dist_px))
|
||||
{
|
||||
is_hit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return is_hit;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
|
||||
#include "ED_screen.h"
|
||||
#include "ED_view3d.h"
|
||||
#include "ED_transform.h"
|
||||
#include "ED_space_api.h"
|
||||
|
||||
#include "BLF_api.h"
|
||||
|
@ -109,6 +110,8 @@ typedef struct RulerInfo {
|
|||
int state;
|
||||
float drag_start_co[3];
|
||||
|
||||
struct SnapObjectContext *snap_context;
|
||||
|
||||
/* wm state */
|
||||
wmWindow *win;
|
||||
ScrArea *sa;
|
||||
|
@ -128,6 +131,7 @@ static RulerItem *ruler_item_add(RulerInfo *ruler_info)
|
|||
static void ruler_item_remove(RulerInfo *ruler_info, RulerItem *ruler_item)
|
||||
{
|
||||
BLI_remlink(&ruler_info->items, ruler_item);
|
||||
|
||||
MEM_freeN(ruler_item);
|
||||
}
|
||||
|
||||
|
@ -632,6 +636,9 @@ static void view3d_ruler_end(const struct bContext *UNUSED(C), RulerInfo *ruler_
|
|||
static void view3d_ruler_free(RulerInfo *ruler_info)
|
||||
{
|
||||
BLI_freelistN(&ruler_info->items);
|
||||
|
||||
ED_transform_snap_object_context_destroy(ruler_info->snap_context);
|
||||
|
||||
MEM_freeN(ruler_info);
|
||||
}
|
||||
|
||||
|
@ -642,11 +649,12 @@ static void view3d_ruler_item_project(RulerInfo *ruler_info, float r_co[3],
|
|||
}
|
||||
|
||||
/* use for mousemove events */
|
||||
static bool view3d_ruler_item_mousemove(bContext *C, RulerInfo *ruler_info, const int mval[2],
|
||||
const bool do_thickness, const bool do_snap)
|
||||
static bool view3d_ruler_item_mousemove(
|
||||
RulerInfo *ruler_info, const int mval[2],
|
||||
const bool do_thickness, const bool do_snap)
|
||||
{
|
||||
const float eps_bias = 0.0002f;
|
||||
const float dist_px = MVAL_MAX_PX_DIST * U.pixelsize; /* snap dist */
|
||||
float dist_px = MVAL_MAX_PX_DIST * U.pixelsize; /* snap dist */
|
||||
RulerItem *ruler_item = ruler_item_active_get(ruler_info);
|
||||
|
||||
ruler_info->snap_flag &= ~RULER_SNAP_OK;
|
||||
|
@ -657,8 +665,8 @@ static bool view3d_ruler_item_mousemove(bContext *C, RulerInfo *ruler_info, cons
|
|||
copy_v3_v3(co, ruler_info->drag_start_co);
|
||||
view3d_ruler_item_project(ruler_info, co, mval);
|
||||
if (do_thickness && ruler_item->co_index != 1) {
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
View3D *v3d = ruler_info->sa->spacedata.first;
|
||||
// Scene *scene = CTX_data_scene(C);
|
||||
// View3D *v3d = ruler_info->sa->spacedata.first;
|
||||
const float mval_fl[2] = {UNPACK2(mval)};
|
||||
float ray_normal[3];
|
||||
float ray_start[3];
|
||||
|
@ -666,33 +674,37 @@ static bool view3d_ruler_item_mousemove(bContext *C, RulerInfo *ruler_info, cons
|
|||
|
||||
co_other = ruler_item->co[ruler_item->co_index == 0 ? 2 : 0];
|
||||
|
||||
if (ED_view3d_snap_from_region(
|
||||
scene, v3d, ruler_info->ar,
|
||||
mval_fl, dist_px,
|
||||
true, false,
|
||||
false, false, true,
|
||||
if (ED_transform_snap_object_project_view3d_mixed(
|
||||
ruler_info->snap_context,
|
||||
&(const struct SnapObjectParams){
|
||||
.snap_select = SNAP_ALL,
|
||||
.snap_to_flag = SCE_SELECT_FACE,
|
||||
},
|
||||
mval_fl, &dist_px, true,
|
||||
co, ray_normal))
|
||||
{
|
||||
negate_v3(ray_normal);
|
||||
/* add some bias */
|
||||
madd_v3_v3v3fl(ray_start, co, ray_normal, eps_bias);
|
||||
ED_view3d_snap_from_ray(
|
||||
scene,
|
||||
ray_start, ray_normal,
|
||||
co_other);
|
||||
ED_transform_snap_object_project_ray(
|
||||
ruler_info->snap_context,
|
||||
ray_start, ray_normal, NULL,
|
||||
co_other, NULL);
|
||||
}
|
||||
}
|
||||
else if (do_snap) {
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
// Scene *scene = CTX_data_scene(C);
|
||||
View3D *v3d = ruler_info->sa->spacedata.first;
|
||||
const float mval_fl[2] = {UNPACK2(mval)};
|
||||
bool use_depth = (v3d->drawtype >= OB_SOLID);
|
||||
|
||||
if (ED_view3d_snap_from_region(
|
||||
scene, v3d, ruler_info->ar,
|
||||
mval_fl, dist_px,
|
||||
use_depth, false,
|
||||
true, true, use_depth,
|
||||
if (ED_transform_snap_object_project_view3d_mixed(
|
||||
ruler_info->snap_context,
|
||||
&(const struct SnapObjectParams){
|
||||
.snap_select = SNAP_ALL,
|
||||
.snap_to_flag = (SCE_SELECT_VERTEX | SCE_SELECT_EDGE) | (use_depth ? SCE_SELECT_FACE : 0),
|
||||
},
|
||||
mval_fl, &dist_px, use_depth,
|
||||
co, NULL))
|
||||
{
|
||||
ruler_info->snap_flag |= RULER_SNAP_OK;
|
||||
|
@ -736,6 +748,10 @@ static int view3d_ruler_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
|
|||
|
||||
op->customdata = ruler_info;
|
||||
|
||||
ruler_info->snap_context = ED_transform_snap_object_context_create_view3d(
|
||||
CTX_data_main(C), CTX_data_scene(C), SNAP_OBJECT_USE_CACHE,
|
||||
ar, CTX_wm_view3d(C));
|
||||
|
||||
ruler_info->win = win;
|
||||
ruler_info->sa = sa;
|
||||
ruler_info->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ruler_info_draw_pixel,
|
||||
|
@ -818,7 +834,7 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
if (use_depth) {
|
||||
/* snap the first point added, not essential but handy */
|
||||
ruler_item->co_index = 0;
|
||||
view3d_ruler_item_mousemove(C, ruler_info, event->mval, false, true);
|
||||
view3d_ruler_item_mousemove(ruler_info, event->mval, false, true);
|
||||
copy_v3_v3(ruler_info->drag_start_co, ruler_item->co[ruler_item->co_index]);
|
||||
}
|
||||
else {
|
||||
|
@ -871,7 +887,7 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
}
|
||||
|
||||
/* update the new location */
|
||||
view3d_ruler_item_mousemove(C, ruler_info, event->mval,
|
||||
view3d_ruler_item_mousemove(ruler_info, event->mval,
|
||||
event->shift != 0, event->ctrl != 0);
|
||||
do_draw = true;
|
||||
}
|
||||
|
@ -920,7 +936,7 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
case MOUSEMOVE:
|
||||
{
|
||||
if (ruler_info->state == RULER_STATE_DRAG) {
|
||||
if (view3d_ruler_item_mousemove(C, ruler_info, event->mval,
|
||||
if (view3d_ruler_item_mousemove(ruler_info, event->mval,
|
||||
event->shift != 0, event->ctrl != 0))
|
||||
{
|
||||
do_draw = true;
|
||||
|
|
|
@ -306,6 +306,8 @@ typedef struct WalkInfo {
|
|||
float jump_height; /* maximum jump height */
|
||||
float speed_factor; /* to use for fast/slow speeds */
|
||||
|
||||
struct SnapObjectContext *snap_context;
|
||||
|
||||
struct View3DCameraControl *v3d_camera_control;
|
||||
|
||||
} WalkInfo;
|
||||
|
@ -402,12 +404,14 @@ static void walk_navigation_mode_set(bContext *C, wmOperator *op, WalkInfo *walk
|
|||
/**
|
||||
* \param r_distance Distance to the hit point
|
||||
*/
|
||||
static bool walk_floor_distance_get(bContext *C, RegionView3D *rv3d, WalkInfo *walk, const float dvec[3], float *r_distance)
|
||||
static bool walk_floor_distance_get(
|
||||
RegionView3D *rv3d, WalkInfo *walk, const float dvec[3],
|
||||
float *r_distance)
|
||||
{
|
||||
float ray_normal[3] = {0, 0, -1}; /* down */
|
||||
float ray_start[3];
|
||||
float r_location[3];
|
||||
float r_normal[3];
|
||||
float r_normal_dummy[3];
|
||||
float dvec_tmp[3];
|
||||
bool ret;
|
||||
|
||||
|
@ -418,12 +422,10 @@ static bool walk_floor_distance_get(bContext *C, RegionView3D *rv3d, WalkInfo *w
|
|||
mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
|
||||
add_v3_v3(ray_start, dvec_tmp);
|
||||
|
||||
ret = snapObjectsRayEx(
|
||||
CTX_data_scene(C), NULL, NULL, NULL, NULL,
|
||||
NULL, SNAP_ALL, SCE_SNAP_MODE_FACE,
|
||||
ret = ED_transform_snap_object_project_ray(
|
||||
walk->snap_context,
|
||||
ray_start, ray_normal, r_distance,
|
||||
r_location, r_normal, NULL, NULL,
|
||||
NULL, NULL);
|
||||
r_location, r_normal_dummy);
|
||||
|
||||
/* artifically scale the distance to the scene size */
|
||||
*r_distance /= walk->grid;
|
||||
|
@ -435,7 +437,9 @@ static bool walk_floor_distance_get(bContext *C, RegionView3D *rv3d, WalkInfo *w
|
|||
* \param r_location Location of the hit point
|
||||
* \param r_normal Normal of the hit surface, transformed to always face the camera
|
||||
*/
|
||||
static bool walk_ray_cast(bContext *C, RegionView3D *rv3d, WalkInfo *walk, float r_location[3], float r_normal[3], float *ray_distance)
|
||||
static bool walk_ray_cast(
|
||||
RegionView3D *rv3d, WalkInfo *walk,
|
||||
float r_location[3], float r_normal[3], float *ray_distance)
|
||||
{
|
||||
float ray_normal[3] = {0, 0, -1}; /* forward */
|
||||
float ray_start[3];
|
||||
|
@ -449,13 +453,10 @@ static bool walk_ray_cast(bContext *C, RegionView3D *rv3d, WalkInfo *walk, float
|
|||
|
||||
normalize_v3(ray_normal);
|
||||
|
||||
ret = snapObjectsRayEx(
|
||||
CTX_data_scene(C), NULL, NULL, NULL, NULL,
|
||||
NULL, SNAP_ALL, SCE_SNAP_MODE_FACE,
|
||||
ray_start, ray_normal, ray_distance,
|
||||
r_location, r_normal, NULL, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
ret = ED_transform_snap_object_project_ray(
|
||||
walk->snap_context,
|
||||
ray_start, ray_normal, NULL,
|
||||
r_location, r_normal);
|
||||
|
||||
/* dot is positive if both rays are facing the same direction */
|
||||
if (dot_v3v3(ray_normal, r_normal) > 0) {
|
||||
|
@ -572,6 +573,9 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
|
|||
|
||||
walk->rv3d->rflag |= RV3D_NAVIGATING;
|
||||
|
||||
walk->snap_context = ED_transform_snap_object_context_create_view3d(
|
||||
CTX_data_main(C), walk->scene, SNAP_OBJECT_USE_CACHE,
|
||||
walk->ar, walk->v3d);
|
||||
|
||||
walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
|
||||
walk->scene, walk->v3d, walk->rv3d,
|
||||
|
@ -622,6 +626,8 @@ static int walkEnd(bContext *C, WalkInfo *walk)
|
|||
|
||||
ED_region_draw_cb_exit(walk->ar->type, walk->draw_handle_pixel);
|
||||
|
||||
ED_transform_snap_object_context_destroy(walk->snap_context);
|
||||
|
||||
ED_view3d_cameracontrol_release(walk->v3d_camera_control, walk->state == WALK_CANCEL);
|
||||
|
||||
rv3d->rflag &= ~RV3D_NAVIGATING;
|
||||
|
@ -894,7 +900,7 @@ static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent
|
|||
{
|
||||
float loc[3], nor[3];
|
||||
float distance;
|
||||
bool ret = walk_ray_cast(C, walk->rv3d, walk, loc, nor, &distance);
|
||||
bool ret = walk_ray_cast(walk->rv3d, walk, loc, nor, &distance);
|
||||
|
||||
/* in case we are teleporting middle way from a jump */
|
||||
walk->speed_jump = 0.0f;
|
||||
|
@ -1175,7 +1181,7 @@ static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk)
|
|||
float difference = -100.0f;
|
||||
float fall_distance;
|
||||
|
||||
ret = walk_floor_distance_get(C, rv3d, walk, dvec, &ray_distance);
|
||||
ret = walk_floor_distance_get(rv3d, walk, dvec, &ray_distance);
|
||||
|
||||
if (ret) {
|
||||
difference = walk->view_height - ray_distance;
|
||||
|
@ -1228,7 +1234,7 @@ static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk)
|
|||
if (t > walk->teleport.duration) {
|
||||
|
||||
/* check to see if we are landing */
|
||||
ret = walk_floor_distance_get(C, rv3d, walk, dvec, &ray_distance);
|
||||
ret = walk_floor_distance_get(rv3d, walk, dvec, &ray_distance);
|
||||
|
||||
if (ret) {
|
||||
difference = walk->view_height - ray_distance;
|
||||
|
|
|
@ -49,6 +49,7 @@ set(SRC
|
|||
transform_ops.c
|
||||
transform_orientations.c
|
||||
transform_snap.c
|
||||
transform_snap_object.c
|
||||
|
||||
transform.h
|
||||
)
|
||||
|
|
|
@ -101,6 +101,11 @@ typedef struct TransSnap {
|
|||
* where the smallest absolute value defines whats closest.
|
||||
*/
|
||||
float (*distance)(struct TransInfo *, const float p1[3], const float p2[3]);
|
||||
|
||||
/**
|
||||
* Re-usable snap context data.
|
||||
*/
|
||||
SnapObjectContext *object_context;
|
||||
} TransSnap;
|
||||
|
||||
typedef struct TransCon {
|
||||
|
@ -677,6 +682,7 @@ bool activeSnap(TransInfo *t);
|
|||
bool validSnap(TransInfo *t);
|
||||
|
||||
void initSnapping(struct TransInfo *t, struct wmOperator *op);
|
||||
void freeSnapping(struct TransInfo *t);
|
||||
void applyProject(TransInfo *t);
|
||||
void applyGridAbsolute(TransInfo *t);
|
||||
void applySnapping(TransInfo *t, float *vec);
|
||||
|
@ -786,4 +792,8 @@ 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
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1502,6 +1502,8 @@ void postTrans(bContext *C, TransInfo *t)
|
|||
if (t->mouse.data) {
|
||||
MEM_freeN(t->mouse.data);
|
||||
}
|
||||
|
||||
freeSnapping(t);
|
||||
}
|
||||
|
||||
void applyTransObjects(TransInfo *t)
|
||||
|
|
|
@ -36,8 +36,6 @@
|
|||
|
||||
#include "PIL_time.h"
|
||||
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_meshdata_types.h" /* Temporary, for snapping to other unselected meshes */
|
||||
|
@ -61,13 +59,11 @@
|
|||
#include "BKE_editmesh.h"
|
||||
#include "BKE_sequencer.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_tracking.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "ED_armature.h"
|
||||
#include "ED_image.h"
|
||||
#include "ED_node.h"
|
||||
#include "ED_uvedit.h"
|
||||
|
@ -83,10 +79,6 @@
|
|||
/* this should be passed as an arg for use in snap functions */
|
||||
#undef BASACT
|
||||
|
||||
#define TRANSFORM_DIST_MAX_PX 1000.0f
|
||||
#define TRANSFORM_SNAP_MAX_PX 100.0f
|
||||
#define TRANSFORM_DIST_INVALID -FLT_MAX
|
||||
|
||||
/* use half of flt-max so we can scale up without an exception */
|
||||
|
||||
/********************* PROTOTYPES ***********************/
|
||||
|
@ -331,8 +323,8 @@ 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, t->tsnap.modeSelect,
|
||||
loc, no, &dist_px))
|
||||
t, mval_fl, t->tsnap.modeSelect, &dist_px,
|
||||
loc, no))
|
||||
{
|
||||
// if (t->flag & (T_EDIT|T_POSE)) {
|
||||
// mul_m4_v3(imat, loc);
|
||||
|
@ -573,6 +565,14 @@ static void initSnappingMode(TransInfo *t)
|
|||
/* Always grid outside of 3D view */
|
||||
t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
|
||||
}
|
||||
|
||||
if (t->flag & (T_OBJECT | T_EDIT)) {
|
||||
if (t->spacetype == SPACE_VIEW3D) {
|
||||
t->tsnap.object_context = ED_transform_snap_object_context_create_view3d(
|
||||
G.main, t->scene, SNAP_OBJECT_USE_CACHE,
|
||||
t->ar, t->view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void initSnapping(TransInfo *t, wmOperator *op)
|
||||
|
@ -636,6 +636,14 @@ void initSnapping(TransInfo *t, wmOperator *op)
|
|||
initSnappingMode(t);
|
||||
}
|
||||
|
||||
void freeSnapping(TransInfo *t)
|
||||
{
|
||||
if (t->tsnap.object_context) {
|
||||
ED_transform_snap_object_context_destroy(t->tsnap.object_context);
|
||||
t->tsnap.object_context = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void setSnappingCallback(TransInfo *t)
|
||||
{
|
||||
t->tsnap.calcSnap = CalcSnapGeometry;
|
||||
|
@ -1002,8 +1010,8 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
|
|||
else {
|
||||
zero_v3(no); /* objects won't set this */
|
||||
found = snapObjectsTransform(
|
||||
t, mval, t->tsnap.modeSelect,
|
||||
loc, no, &dist_px);
|
||||
t, mval, t->tsnap.modeSelect, &dist_px,
|
||||
loc, no);
|
||||
}
|
||||
|
||||
if (found == true) {
|
||||
|
@ -1237,884 +1245,26 @@ static void TargetSnapClosest(TransInfo *t)
|
|||
}
|
||||
}
|
||||
|
||||
static bool snapEdge(
|
||||
ARegion *ar, const float v1co[3], const short v1no[3], const float v2co[3], const short v2no[3],
|
||||
float obmat[4][4], float timat[3][3], const float mval_fl[2],
|
||||
const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], float *ray_depth,
|
||||
float r_loc[3], float r_no[3], float *r_dist_px)
|
||||
{
|
||||
float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3];
|
||||
int result;
|
||||
bool retval = false;
|
||||
|
||||
copy_v3_v3(ray_end, ray_normal_local);
|
||||
mul_v3_fl(ray_end, 2000);
|
||||
add_v3_v3v3(ray_end, ray_start_local, ray_end);
|
||||
|
||||
result = isect_line_line_v3(v1co, v2co, ray_start_local, ray_end, intersect, dvec); /* dvec used but we don't care about result */
|
||||
|
||||
if (result) {
|
||||
float edge_loc[3], vec[3];
|
||||
float mul;
|
||||
|
||||
/* check for behind ray_start */
|
||||
sub_v3_v3v3(dvec, intersect, ray_start_local);
|
||||
|
||||
sub_v3_v3v3(edge_loc, v1co, v2co);
|
||||
sub_v3_v3v3(vec, intersect, v2co);
|
||||
|
||||
mul = dot_v3v3(vec, edge_loc) / dot_v3v3(edge_loc, edge_loc);
|
||||
|
||||
if (mul > 1) {
|
||||
mul = 1;
|
||||
copy_v3_v3(intersect, v1co);
|
||||
}
|
||||
else if (mul < 0) {
|
||||
mul = 0;
|
||||
copy_v3_v3(intersect, v2co);
|
||||
}
|
||||
|
||||
if (dot_v3v3(ray_normal_local, dvec) > 0) {
|
||||
float location[3];
|
||||
float new_depth;
|
||||
float screen_loc[2];
|
||||
float new_dist;
|
||||
|
||||
copy_v3_v3(location, intersect);
|
||||
|
||||
mul_m4_v3(obmat, location);
|
||||
|
||||
new_depth = len_v3v3(location, ray_start);
|
||||
|
||||
if (ED_view3d_project_float_global(ar, location, screen_loc, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
|
||||
new_dist = len_manhattan_v2v2(mval_fl, screen_loc);
|
||||
}
|
||||
else {
|
||||
new_dist = TRANSFORM_DIST_MAX_PX;
|
||||
}
|
||||
|
||||
/* 10% threshold if edge is closer but a bit further
|
||||
* this takes care of series of connected edges a bit slanted w.r.t the viewport
|
||||
* otherwise, it would stick to the verts of the closest edge and not slide along merrily
|
||||
* */
|
||||
if (new_dist <= *r_dist_px && new_depth < *ray_depth * 1.001f) {
|
||||
float n1[3], n2[3];
|
||||
|
||||
*ray_depth = new_depth;
|
||||
retval = true;
|
||||
|
||||
sub_v3_v3v3(edge_loc, v1co, v2co);
|
||||
sub_v3_v3v3(vec, intersect, v2co);
|
||||
|
||||
mul = dot_v3v3(vec, edge_loc) / dot_v3v3(edge_loc, edge_loc);
|
||||
|
||||
if (r_no) {
|
||||
normal_short_to_float_v3(n1, v1no);
|
||||
normal_short_to_float_v3(n2, v2no);
|
||||
interp_v3_v3v3(r_no, n2, n1, mul);
|
||||
mul_m3_v3(timat, r_no);
|
||||
normalize_v3(r_no);
|
||||
}
|
||||
|
||||
copy_v3_v3(r_loc, location);
|
||||
|
||||
*r_dist_px = new_dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool snapVertex(
|
||||
ARegion *ar, const float vco[3], const short vno[3],
|
||||
float obmat[4][4], float timat[3][3], const float mval_fl[2],
|
||||
const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], float *ray_depth,
|
||||
float r_loc[3], float r_no[3], float *r_dist_px)
|
||||
{
|
||||
bool retval = false;
|
||||
float dvec[3];
|
||||
|
||||
sub_v3_v3v3(dvec, vco, ray_start_local);
|
||||
|
||||
if (dot_v3v3(ray_normal_local, dvec) > 0) {
|
||||
float location[3];
|
||||
float new_depth;
|
||||
float screen_loc[2];
|
||||
float new_dist;
|
||||
|
||||
copy_v3_v3(location, vco);
|
||||
|
||||
mul_m4_v3(obmat, location);
|
||||
|
||||
new_depth = len_v3v3(location, ray_start);
|
||||
|
||||
if (ED_view3d_project_float_global(ar, location, screen_loc, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
|
||||
new_dist = len_manhattan_v2v2(mval_fl, screen_loc);
|
||||
}
|
||||
else {
|
||||
new_dist = TRANSFORM_DIST_MAX_PX;
|
||||
}
|
||||
|
||||
|
||||
if (new_dist <= *r_dist_px && new_depth < *ray_depth) {
|
||||
*ray_depth = new_depth;
|
||||
retval = true;
|
||||
|
||||
copy_v3_v3(r_loc, location);
|
||||
|
||||
if (r_no) {
|
||||
normal_short_to_float_v3(r_no, vno);
|
||||
mul_m3_v3(timat, r_no);
|
||||
normalize_v3(r_no);
|
||||
}
|
||||
|
||||
*r_dist_px = new_dist;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool snapArmature(
|
||||
ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4],
|
||||
const float mval[2], const short snap_to,
|
||||
const float ray_start[3], const float ray_normal[3], float *ray_depth,
|
||||
float r_loc[3], float *UNUSED(r_no), float *r_dist_px)
|
||||
{
|
||||
float imat[4][4];
|
||||
float ray_start_local[3], ray_normal_local[3];
|
||||
bool retval = false;
|
||||
|
||||
invert_m4_m4(imat, obmat);
|
||||
|
||||
mul_v3_m4v3(ray_start_local, imat, ray_start);
|
||||
mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
|
||||
|
||||
if (arm->edbo) {
|
||||
EditBone *eBone;
|
||||
|
||||
for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
|
||||
if (eBone->layer & arm->layer) {
|
||||
/* skip hidden or moving (selected) bones */
|
||||
if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
|
||||
switch (snap_to) {
|
||||
case SCE_SNAP_MODE_VERTEX:
|
||||
retval |= snapVertex(ar, eBone->head, NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
|
||||
retval |= snapVertex(ar, eBone->tail, NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
|
||||
break;
|
||||
case SCE_SNAP_MODE_EDGE:
|
||||
retval |= snapEdge(ar, eBone->head, NULL, eBone->tail, NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ob->pose && ob->pose->chanbase.first) {
|
||||
bPoseChannel *pchan;
|
||||
Bone *bone;
|
||||
|
||||
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
|
||||
bone = pchan->bone;
|
||||
/* skip hidden bones */
|
||||
if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
|
||||
const float *head_vec = pchan->pose_head;
|
||||
const float *tail_vec = pchan->pose_tail;
|
||||
|
||||
switch (snap_to) {
|
||||
case SCE_SNAP_MODE_VERTEX:
|
||||
retval |= snapVertex(ar, head_vec, NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
|
||||
retval |= snapVertex(ar, tail_vec, NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
|
||||
break;
|
||||
case SCE_SNAP_MODE_EDGE:
|
||||
retval |= snapEdge(ar, head_vec, NULL, tail_vec, NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool snapCurve(
|
||||
ARegion *ar, Object *ob, Curve *cu, float obmat[4][4],
|
||||
const float mval[2], const short snap_to,
|
||||
const float ray_start[3], const float ray_normal[3], float *ray_depth,
|
||||
float r_loc[3], float *UNUSED(r_no), float *r_dist_px)
|
||||
{
|
||||
float imat[4][4];
|
||||
float ray_start_local[3], ray_normal_local[3];
|
||||
bool retval = false;
|
||||
int u;
|
||||
|
||||
Nurb *nu;
|
||||
|
||||
/* only vertex snapping mode (eg control points and handles) supported for now) */
|
||||
if (snap_to != SCE_SNAP_MODE_VERTEX) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
invert_m4_m4(imat, obmat);
|
||||
|
||||
copy_v3_v3(ray_start_local, ray_start);
|
||||
copy_v3_v3(ray_normal_local, ray_normal);
|
||||
|
||||
mul_m4_v3(imat, ray_start_local);
|
||||
mul_mat3_m4_v3(imat, ray_normal_local);
|
||||
|
||||
for (nu = (ob->mode == OB_MODE_EDIT ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
|
||||
for (u = 0; u < nu->pntsu; u++) {
|
||||
switch (snap_to) {
|
||||
case SCE_SNAP_MODE_VERTEX:
|
||||
{
|
||||
if (ob->mode == OB_MODE_EDIT) {
|
||||
if (nu->bezt) {
|
||||
/* don't snap to selected (moving) or hidden */
|
||||
if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) {
|
||||
break;
|
||||
}
|
||||
retval |= snapVertex(ar, nu->bezt[u].vec[1], NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
|
||||
/* don't snap if handle is selected (moving), or if it is aligning to a moving handle */
|
||||
if (!(nu->bezt[u].f1 & SELECT) && !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT)) {
|
||||
retval |= snapVertex(ar, nu->bezt[u].vec[0], NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
|
||||
}
|
||||
if (!(nu->bezt[u].f3 & SELECT) && !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT)) {
|
||||
retval |= snapVertex(ar, nu->bezt[u].vec[2], NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* don't snap to selected (moving) or hidden */
|
||||
if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) {
|
||||
break;
|
||||
}
|
||||
retval |= snapVertex(ar, nu->bp[u].vec, NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* curve is not visible outside editmode if nurb length less than two */
|
||||
if (nu->pntsu > 1) {
|
||||
if (nu->bezt) {
|
||||
retval |= snapVertex(ar, nu->bezt[u].vec[1], NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
|
||||
}
|
||||
else {
|
||||
retval |= snapVertex(ar, nu->bp[u].vec, NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
|
||||
{
|
||||
const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
|
||||
return index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
|
||||
}
|
||||
|
||||
static bool snapDerivedMesh(
|
||||
ARegion *ar, Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[4][4],
|
||||
const float mval[2], const short snap_to, bool do_bb,
|
||||
const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
|
||||
float r_loc[3], float r_no[3], float *r_dist_px, int *r_index)
|
||||
{
|
||||
bool retval = false;
|
||||
int totvert = dm->getNumVerts(dm);
|
||||
|
||||
if (totvert > 0) {
|
||||
const bool do_ray_start_correction = (
|
||||
ELEM(snap_to, SCE_SNAP_MODE_FACE, SCE_SNAP_MODE_VERTEX) &&
|
||||
(ar && !((RegionView3D *)ar->regiondata)->is_persp));
|
||||
bool need_ray_start_correction_init = do_ray_start_correction;
|
||||
|
||||
float imat[4][4];
|
||||
float timat[3][3]; /* transpose inverse matrix for normals */
|
||||
float ray_start_local[3], ray_normal_local[3];
|
||||
float local_scale, local_depth, len_diff;
|
||||
|
||||
BVHTreeFromMesh treedata = {0};
|
||||
|
||||
invert_m4_m4(imat, obmat);
|
||||
transpose_m3_m4(timat, imat);
|
||||
|
||||
copy_v3_v3(ray_start_local, ray_start);
|
||||
copy_v3_v3(ray_normal_local, ray_normal);
|
||||
|
||||
mul_m4_v3(imat, ray_start_local);
|
||||
mul_mat3_m4_v3(imat, ray_normal_local);
|
||||
|
||||
/* local scale in normal direction */
|
||||
local_scale = normalize_v3(ray_normal_local);
|
||||
local_depth = *ray_depth;
|
||||
if (local_depth != BVH_RAYCAST_DIST_MAX) {
|
||||
local_depth *= local_scale;
|
||||
}
|
||||
|
||||
if (do_bb) {
|
||||
BoundBox *bb = BKE_object_boundbox_get(ob);
|
||||
|
||||
if (bb) {
|
||||
BoundBox bb_temp;
|
||||
|
||||
/* We cannot aford a bbox with some null dimension, which may happen in some cases...
|
||||
* Threshold is rather high, but seems to be needed to get good behavior, see T46099. */
|
||||
bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f);
|
||||
|
||||
/* Exact value here is arbitrary (ideally we would scale in pixel-space based on 'r_dist_px'),
|
||||
* scale up so we can snap against verts & edges on the boundbox, see T46816. */
|
||||
if (ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
|
||||
BKE_boundbox_scale(&bb_temp, bb, 1.0f + 1e-1f);
|
||||
bb = &bb_temp;
|
||||
}
|
||||
|
||||
/* was local_depth, see: T47838 */
|
||||
len_diff = BVH_RAYCAST_DIST_MAX;
|
||||
|
||||
if (!BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, &len_diff)) {
|
||||
return retval;
|
||||
}
|
||||
need_ray_start_correction_init = false;
|
||||
}
|
||||
}
|
||||
|
||||
treedata.em_evil = em;
|
||||
treedata.em_evil_all = false;
|
||||
switch (snap_to) {
|
||||
case SCE_SNAP_MODE_FACE:
|
||||
bvhtree_from_mesh_looptri(&treedata, dm, 0.0f, 4, 6);
|
||||
break;
|
||||
case SCE_SNAP_MODE_VERTEX:
|
||||
bvhtree_from_mesh_verts(&treedata, dm, 0.0f, 2, 6);
|
||||
break;
|
||||
}
|
||||
|
||||
if (need_ray_start_correction_init) {
|
||||
/* We *need* a reasonably valid len_diff in this case.
|
||||
* Use BHVTree to find the closest face from ray_start_local.
|
||||
*/
|
||||
BVHTreeNearest nearest;
|
||||
|
||||
if (treedata.tree != NULL) {
|
||||
nearest.index = -1;
|
||||
nearest.dist_sq = FLT_MAX;
|
||||
/* Compute and store result. */
|
||||
BLI_bvhtree_find_nearest(
|
||||
treedata.tree, ray_start_local, &nearest, treedata.nearest_callback, &treedata);
|
||||
if (nearest.index != -1) {
|
||||
len_diff = sqrtf(nearest.dist_sq);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already
|
||||
* been *inside* boundbox, leading to snap failures (see T38409).
|
||||
* Note also ar might be null (see T38435), in this case we assume ray_start is ok!
|
||||
*/
|
||||
if (do_ray_start_correction) {
|
||||
float ray_org_local[3];
|
||||
|
||||
copy_v3_v3(ray_org_local, ray_origin);
|
||||
mul_m4_v3(imat, ray_org_local);
|
||||
|
||||
/* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with very far
|
||||
* away ray_start values (as returned in case of ortho view3d), see T38358.
|
||||
*/
|
||||
len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
|
||||
madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local,
|
||||
len_diff - len_v3v3(ray_start_local, ray_org_local));
|
||||
local_depth -= len_diff;
|
||||
}
|
||||
else {
|
||||
len_diff = 0.0f;
|
||||
}
|
||||
|
||||
switch (snap_to) {
|
||||
case SCE_SNAP_MODE_FACE:
|
||||
{
|
||||
BVHTreeRayHit hit;
|
||||
|
||||
hit.index = -1;
|
||||
hit.dist = local_depth;
|
||||
|
||||
if (treedata.tree &&
|
||||
BLI_bvhtree_ray_cast(treedata.tree, ray_start_local, ray_normal_local, 0.0f,
|
||||
&hit, treedata.raycast_callback, &treedata) != -1)
|
||||
{
|
||||
hit.dist += len_diff;
|
||||
hit.dist /= local_scale;
|
||||
if (hit.dist <= *ray_depth) {
|
||||
*ray_depth = hit.dist;
|
||||
copy_v3_v3(r_loc, hit.co);
|
||||
copy_v3_v3(r_no, hit.no);
|
||||
|
||||
/* back to worldspace */
|
||||
mul_m4_v3(obmat, r_loc);
|
||||
mul_m3_v3(timat, r_no);
|
||||
normalize_v3(r_no);
|
||||
|
||||
retval = true;
|
||||
|
||||
if (r_index) {
|
||||
*r_index = dm_looptri_to_poly_index(dm, &treedata.looptri[hit.index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCE_SNAP_MODE_VERTEX:
|
||||
{
|
||||
BVHTreeNearest nearest;
|
||||
|
||||
nearest.index = -1;
|
||||
nearest.dist_sq = local_depth * local_depth;
|
||||
if (treedata.tree &&
|
||||
BLI_bvhtree_find_nearest_to_ray(
|
||||
treedata.tree, ray_start_local, ray_normal_local,
|
||||
&nearest, NULL, NULL) != -1)
|
||||
{
|
||||
const MVert *v = &treedata.vert[nearest.index];
|
||||
retval = snapVertex(
|
||||
ar, v->co, v->no, obmat, timat, mval,
|
||||
ray_start, ray_start_local, ray_normal_local, ray_depth,
|
||||
r_loc, r_no, r_dist_px);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCE_SNAP_MODE_EDGE:
|
||||
{
|
||||
MVert *verts = dm->getVertArray(dm);
|
||||
MEdge *edges = dm->getEdgeArray(dm);
|
||||
int totedge = dm->getNumEdges(dm);
|
||||
const int *index_array = NULL;
|
||||
int index = 0;
|
||||
int i;
|
||||
|
||||
if (em != NULL) {
|
||||
index_array = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
|
||||
BM_mesh_elem_table_ensure(em->bm, BM_EDGE);
|
||||
}
|
||||
|
||||
for (i = 0; i < totedge; i++) {
|
||||
MEdge *e = edges + i;
|
||||
bool test = true;
|
||||
|
||||
if (em != NULL) {
|
||||
if (index_array) {
|
||||
index = index_array[i];
|
||||
}
|
||||
else {
|
||||
index = i;
|
||||
}
|
||||
|
||||
if (index == ORIGINDEX_NONE) {
|
||||
test = false;
|
||||
}
|
||||
else {
|
||||
BMEdge *eed = BM_edge_at_index(em->bm, index);
|
||||
|
||||
if (BM_elem_flag_test(eed, BM_ELEM_HIDDEN) ||
|
||||
BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
|
||||
BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))
|
||||
{
|
||||
test = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (test) {
|
||||
retval |= snapEdge(
|
||||
ar, verts[e->v1].co, verts[e->v1].no, verts[e->v2].co, verts[e->v2].no, obmat, timat,
|
||||
mval, ray_start, ray_start_local, ray_normal_local, ray_depth,
|
||||
r_loc, r_no, r_dist_px);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free_bvhtree_from_mesh(&treedata);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* may extend later (for now just snaps to empty center) */
|
||||
static bool snapEmpty(
|
||||
ARegion *ar, Object *ob, float obmat[4][4],
|
||||
const float mval[2], const short snap_to,
|
||||
const float ray_start[3], const float ray_normal[3], float *ray_depth,
|
||||
float r_loc[3], float *UNUSED(r_no), float *r_dist_px)
|
||||
{
|
||||
float imat[4][4];
|
||||
float ray_start_local[3], ray_normal_local[3];
|
||||
bool retval = false;
|
||||
|
||||
if (ob->transflag & OB_DUPLI) {
|
||||
return retval;
|
||||
}
|
||||
/* for now only vertex supported */
|
||||
if (snap_to != SCE_SNAP_MODE_VERTEX) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
invert_m4_m4(imat, obmat);
|
||||
|
||||
mul_v3_m4v3(ray_start_local, imat, ray_start);
|
||||
mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
|
||||
|
||||
switch (snap_to) {
|
||||
case SCE_SNAP_MODE_VERTEX:
|
||||
{
|
||||
const float zero_co[3] = {0.0f};
|
||||
retval |= snapVertex(
|
||||
ar, zero_co, NULL, obmat, NULL, mval,
|
||||
ray_start, ray_start_local, ray_normal_local, ray_depth,
|
||||
r_loc, NULL, r_dist_px);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool snapCamera(
|
||||
ARegion *ar, Scene *scene, Object *object, float obmat[4][4],
|
||||
const float mval[2], const short snap_to,
|
||||
const float ray_start[3], const float ray_normal[3], float *ray_depth,
|
||||
float r_loc[3], float *UNUSED(r_no), float *r_dist_px)
|
||||
{
|
||||
float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4];
|
||||
bool retval = false;
|
||||
MovieClip *clip = BKE_object_movieclip_get(scene, object, false);
|
||||
MovieTracking *tracking;
|
||||
float ray_start_local[3], ray_normal_local[3];
|
||||
|
||||
if (clip == NULL) {
|
||||
return retval;
|
||||
}
|
||||
if (object->transflag & OB_DUPLI) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
tracking = &clip->tracking;
|
||||
|
||||
BKE_tracking_get_camera_object_matrix(scene, object, orig_camera_mat);
|
||||
|
||||
invert_m4_m4(orig_camera_imat, orig_camera_mat);
|
||||
invert_m4_m4(imat, obmat);
|
||||
|
||||
switch (snap_to) {
|
||||
case SCE_SNAP_MODE_VERTEX:
|
||||
{
|
||||
MovieTrackingObject *tracking_object;
|
||||
|
||||
for (tracking_object = tracking->objects.first;
|
||||
tracking_object;
|
||||
tracking_object = tracking_object->next)
|
||||
{
|
||||
ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
|
||||
MovieTrackingTrack *track;
|
||||
float reconstructed_camera_mat[4][4],
|
||||
reconstructed_camera_imat[4][4];
|
||||
float (*vertex_obmat)[4];
|
||||
|
||||
copy_v3_v3(ray_start_local, ray_start);
|
||||
copy_v3_v3(ray_normal_local, ray_normal);
|
||||
|
||||
if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) {
|
||||
BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object,
|
||||
CFRA, reconstructed_camera_mat);
|
||||
|
||||
invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat);
|
||||
}
|
||||
|
||||
for (track = tracksbase->first; track; track = track->next) {
|
||||
float bundle_pos[3];
|
||||
|
||||
if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
copy_v3_v3(bundle_pos, track->bundle_pos);
|
||||
if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
|
||||
mul_m4_v3(orig_camera_imat, ray_start_local);
|
||||
mul_mat3_m4_v3(orig_camera_imat, ray_normal_local);
|
||||
vertex_obmat = orig_camera_mat;
|
||||
}
|
||||
else {
|
||||
mul_m4_v3(reconstructed_camera_imat, bundle_pos);
|
||||
mul_m4_v3(imat, ray_start_local);
|
||||
mul_mat3_m4_v3(imat, ray_normal_local);
|
||||
vertex_obmat = obmat;
|
||||
}
|
||||
|
||||
retval |= snapVertex(
|
||||
ar, bundle_pos, NULL, vertex_obmat, NULL, mval,
|
||||
ray_start, ray_start_local, ray_normal_local, ray_depth,
|
||||
r_loc, NULL, r_dist_px);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool snapObject(
|
||||
Scene *scene, ARegion *ar, Object *ob, float obmat[4][4], bool use_obedit,
|
||||
const float mval[2], const short snap_to,
|
||||
const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
|
||||
/* return args */
|
||||
float r_loc[3], float r_no[3], float *r_dist_px, int *r_index,
|
||||
Object **r_ob, float r_obmat[4][4])
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
if (ob->type == OB_MESH) {
|
||||
BMEditMesh *em;
|
||||
DerivedMesh *dm;
|
||||
bool do_bb = true;
|
||||
|
||||
if (use_obedit) {
|
||||
em = BKE_editmesh_from_object(ob);
|
||||
dm = editbmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH);
|
||||
do_bb = false;
|
||||
}
|
||||
else {
|
||||
/* in this case we want the mesh from the editmesh, avoids stale data. see: T45978.
|
||||
* still set the 'em' to NULL, since we only want the 'dm'. */
|
||||
em = BKE_editmesh_from_object(ob);
|
||||
if (em) {
|
||||
editbmesh_get_derived_cage_and_final(scene, ob, em, CD_MASK_BAREMESH, &dm);
|
||||
}
|
||||
else {
|
||||
dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
|
||||
}
|
||||
em = NULL;
|
||||
}
|
||||
|
||||
retval = snapDerivedMesh(
|
||||
ar, ob, dm, em, obmat, mval, snap_to, do_bb,
|
||||
ray_start, ray_normal, ray_origin, ray_depth,
|
||||
r_loc, r_no, r_dist_px, r_index);
|
||||
|
||||
dm->release(dm);
|
||||
}
|
||||
else if (ob->type == OB_ARMATURE) {
|
||||
retval = snapArmature(
|
||||
ar, ob, ob->data, obmat, mval, snap_to,
|
||||
ray_start, ray_normal, ray_depth,
|
||||
r_loc, r_no, r_dist_px);
|
||||
}
|
||||
else if (ob->type == OB_CURVE) {
|
||||
retval = snapCurve(
|
||||
ar, ob, ob->data, obmat, mval, snap_to,
|
||||
ray_start, ray_normal, ray_depth,
|
||||
r_loc, r_no, r_dist_px);
|
||||
}
|
||||
else if (ob->type == OB_EMPTY) {
|
||||
retval = snapEmpty(
|
||||
ar, ob, obmat, mval, snap_to,
|
||||
ray_start, ray_normal, ray_depth,
|
||||
r_loc, r_no, r_dist_px);
|
||||
}
|
||||
else if (ob->type == OB_CAMERA) {
|
||||
retval = snapCamera(
|
||||
ar, scene, ob, obmat, mval, snap_to,
|
||||
ray_start, ray_normal, ray_depth,
|
||||
r_loc, r_no, r_dist_px);
|
||||
}
|
||||
|
||||
if (retval) {
|
||||
if (r_ob) {
|
||||
*r_ob = ob;
|
||||
copy_m4_m4(r_obmat, obmat);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool snapObjectsRay(
|
||||
Scene *scene, View3D *v3d, ARegion *ar, Base *base_act, Object *obedit,
|
||||
const float mval[2], SnapSelect snap_select, const short snap_to,
|
||||
const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
|
||||
/* return args */
|
||||
float r_loc[3], float r_no[3], float *r_dist_px, int *r_index,
|
||||
Object **r_ob, float r_obmat[4][4])
|
||||
{
|
||||
Base *base;
|
||||
bool retval = false;
|
||||
|
||||
if (snap_select == SNAP_ALL && obedit) {
|
||||
Object *ob = obedit;
|
||||
|
||||
retval |= snapObject(
|
||||
scene, ar, ob, ob->obmat, true,
|
||||
mval, snap_to,
|
||||
ray_start, ray_normal, ray_origin, ray_depth,
|
||||
r_loc, r_no, r_dist_px, r_index, r_ob, r_obmat);
|
||||
}
|
||||
|
||||
/* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA
|
||||
* which makes the loop skip it, even the derived mesh will never change
|
||||
*
|
||||
* To solve that problem, we do it first as an exception.
|
||||
* */
|
||||
base = base_act;
|
||||
if (base && base->object && base->object->mode & OB_MODE_PARTICLE_EDIT) {
|
||||
Object *ob = base->object;
|
||||
retval |= snapObject(
|
||||
scene, ar, ob, ob->obmat, false,
|
||||
mval, snap_to,
|
||||
ray_start, ray_normal, ray_origin, ray_depth,
|
||||
r_loc, r_no, r_dist_px, r_index, r_ob, r_obmat);
|
||||
}
|
||||
|
||||
for (base = FIRSTBASE; base != NULL; base = base->next) {
|
||||
if ((BASE_VISIBLE_BGMODE(v3d, scene, base)) &&
|
||||
(base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 &&
|
||||
|
||||
((snap_select == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL)) == 0) ||
|
||||
(ELEM(snap_select, SNAP_ALL, SNAP_NOT_OBEDIT) && base != base_act)))
|
||||
{
|
||||
Object *ob = base->object;
|
||||
Object *ob_snap = ob;
|
||||
bool use_obedit = false;
|
||||
|
||||
/* for linked objects, use the same object but a different matrix */
|
||||
if (obedit && ob->data == obedit->data) {
|
||||
use_obedit = true;
|
||||
ob_snap = obedit;
|
||||
}
|
||||
|
||||
if (ob->transflag & OB_DUPLI) {
|
||||
DupliObject *dupli_ob;
|
||||
ListBase *lb = object_duplilist(G.main->eval_ctx, scene, ob);
|
||||
|
||||
for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
|
||||
bool use_obedit_dupli = (obedit && dupli_ob->ob->data == obedit->data);
|
||||
Object *dupli_snap = (use_obedit_dupli) ? obedit : dupli_ob->ob;
|
||||
|
||||
retval |= snapObject(
|
||||
scene, ar, dupli_snap, dupli_ob->mat, use_obedit_dupli,
|
||||
mval, snap_to,
|
||||
ray_start, ray_normal, ray_origin, ray_depth,
|
||||
r_loc, r_no, r_dist_px, r_index, r_ob, r_obmat);
|
||||
}
|
||||
|
||||
free_object_duplilist(lb);
|
||||
}
|
||||
|
||||
retval |= snapObject(
|
||||
scene, ar, ob_snap, ob->obmat, use_obedit,
|
||||
mval, snap_to,
|
||||
ray_start, ray_normal, ray_origin, ray_depth,
|
||||
r_loc, r_no, r_dist_px, r_index, r_ob, r_obmat);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
static bool snapObjects(
|
||||
Scene *scene, View3D *v3d, ARegion *ar, Base *base_act, Object *obedit,
|
||||
const float mval[2], SnapSelect snap_select, const short snap_to,
|
||||
float *ray_depth,
|
||||
float r_loc[3], float r_no[3], float *r_dist_px, int *r_index)
|
||||
{
|
||||
float ray_start[3], ray_normal[3], ray_orgigin[3];
|
||||
|
||||
if (!ED_view3d_win_to_ray_ex(ar, v3d, mval, ray_orgigin, ray_normal, ray_start, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return snapObjectsRay(
|
||||
scene, v3d, ar, base_act, obedit,
|
||||
mval, snap_select, snap_to,
|
||||
ray_start, ray_normal, ray_orgigin, ray_depth,
|
||||
r_loc, r_no, r_dist_px, r_index, NULL, NULL);
|
||||
}
|
||||
|
||||
bool snapObjectsTransform(
|
||||
TransInfo *t, const float mval[2], SnapSelect snap_select,
|
||||
float r_loc[3], float r_no[3], float *r_dist_px)
|
||||
float *dist_px,
|
||||
float r_loc[3], float r_no[3])
|
||||
{
|
||||
float ray_dist = BVH_RAYCAST_DIST_MAX;
|
||||
Object *obedit = NULL;
|
||||
Base *base_act = NULL;
|
||||
|
||||
if (t->flag & T_EDIT) {
|
||||
obedit = t->obedit;
|
||||
}
|
||||
|
||||
if ((t->options & CTX_GPENCIL_STROKES) == 0) {
|
||||
base_act = t->scene->basact;
|
||||
}
|
||||
|
||||
return snapObjects(
|
||||
t->scene, t->view, t->ar, base_act, obedit,
|
||||
mval, snap_select, t->scene->toolsettings->snap_mode,
|
||||
return ED_transform_snap_object_project_view3d_ex(
|
||||
t->tsnap.object_context,
|
||||
&(const struct SnapObjectParams){
|
||||
.snap_select = snap_select,
|
||||
.snap_to = t->scene->toolsettings->snap_mode,
|
||||
.use_object_edit = (t->flag & T_EDIT) != 0,
|
||||
.use_object_active = (t->options & CTX_GPENCIL_STROKES) == 0,
|
||||
},
|
||||
mval, dist_px,
|
||||
&ray_dist,
|
||||
r_loc, r_no, r_dist_px, NULL);
|
||||
r_loc, r_no, NULL);
|
||||
}
|
||||
|
||||
bool snapObjectsContext(
|
||||
bContext *C, const float mval[2], SnapSelect snap_select,
|
||||
float r_loc[3], float r_no[3], float *r_dist_px)
|
||||
{
|
||||
ScrArea *sa = CTX_wm_area(C);
|
||||
View3D *v3d = sa->spacedata.first;
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
Object *obedit = CTX_data_edit_object(C);
|
||||
float ray_dist = BVH_RAYCAST_DIST_MAX;
|
||||
|
||||
return snapObjects(
|
||||
scene, v3d, ar, scene->basact, obedit,
|
||||
mval, snap_select, scene->toolsettings->snap_mode,
|
||||
&ray_dist,
|
||||
r_loc, r_no, r_dist_px, NULL);
|
||||
}
|
||||
|
||||
bool snapObjectsEx(
|
||||
Scene *scene, View3D *v3d, ARegion *ar, Base *base_act, Object *obedit,
|
||||
const float mval[2], SnapSelect snap_select, const short snap_to,
|
||||
float *ray_depth,
|
||||
float r_loc[3], float r_no[3], float *r_dist_px)
|
||||
{
|
||||
return snapObjects(
|
||||
scene, v3d, ar, base_act, obedit,
|
||||
mval, snap_select, snap_to,
|
||||
ray_depth,
|
||||
r_loc, r_no, r_dist_px, NULL);
|
||||
}
|
||||
bool snapObjectsRayEx(
|
||||
Scene *scene, View3D *v3d, ARegion *ar, Base *base_act, Object *obedit,
|
||||
const float mval[2], SnapSelect snap_select, const short snap_to,
|
||||
const float ray_start[3], const float ray_normal[3], float *ray_depth,
|
||||
float r_loc[3], float r_no[3], float *r_dist_px, int *r_index,
|
||||
Object **r_ob, float r_obmat[4][4])
|
||||
{
|
||||
return snapObjectsRay(
|
||||
scene, v3d, ar, base_act, obedit,
|
||||
mval, snap_select, snap_to,
|
||||
ray_start, ray_normal, ray_start, ray_depth,
|
||||
r_loc, r_no, r_dist_px, r_index,
|
||||
r_ob, r_obmat);
|
||||
}
|
||||
|
||||
/******************** PEELING *********************************/
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -145,13 +145,22 @@ static void rna_Scene_ray_cast(
|
|||
{
|
||||
normalize_v3(direction);
|
||||
|
||||
if (snapObjectsRayEx(
|
||||
scene, NULL, NULL, NULL, NULL,
|
||||
NULL, SNAP_ALL, SCE_SNAP_MODE_FACE,
|
||||
SnapObjectContext *sctx = ED_transform_snap_object_context_create(
|
||||
G.main, scene, 0);
|
||||
|
||||
bool ret = ED_transform_snap_object_project_ray_ex(
|
||||
sctx,
|
||||
&(const struct SnapObjectParams){
|
||||
.snap_select = SNAP_ALL,
|
||||
.snap_to = SCE_SNAP_MODE_FACE,
|
||||
},
|
||||
origin, direction, &ray_dist,
|
||||
r_location, r_normal, NULL, r_index,
|
||||
r_ob, (float(*)[4])r_obmat))
|
||||
{
|
||||
r_location, r_normal, r_index,
|
||||
r_ob, (float(*)[4])r_obmat);
|
||||
|
||||
ED_transform_snap_object_context_destroy(sctx);
|
||||
|
||||
if (ret) {
|
||||
*r_success = true;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -519,11 +519,18 @@ bool ED_texture_context_check_others(const struct bContext *C) RET_ZERO
|
|||
|
||||
bool ED_text_region_location_from_cursor(SpaceText *st, ARegion *ar, const int cursor_co[2], int r_pixel_co[2]) RET_ZERO
|
||||
|
||||
bool snapObjectsRayEx(
|
||||
struct Scene *scene, struct View3D *v3d, struct ARegion *ar, struct Base *base_act, struct Object *obedit,
|
||||
const float mval[2], SnapSelect snap_select, short snap_mode,
|
||||
const float ray_start[3], const float ray_normal[3], float *ray_dist,
|
||||
float r_loc[3], float r_no[3], float *r_dist_px, int *r_index,
|
||||
SnapObjectContext *ED_transform_snap_object_context_create(
|
||||
struct Main *bmain, struct Scene *scene, int flag) RET_NULL
|
||||
SnapObjectContext *ED_transform_snap_object_context_create_view3d(
|
||||
struct Main *bmain, struct Scene *scene, int flag,
|
||||
struct ARegion *ar, struct View3D *v3d) RET_NULL
|
||||
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx) RET_NONE
|
||||
bool ED_transform_snap_object_project_ray_ex(
|
||||
struct SnapObjectContext *sctx,
|
||||
const struct SnapObjectParams *params,
|
||||
const float ray_start[3], const float ray_normal[3], float *ray_depth,
|
||||
/* return args */
|
||||
float r_loc[3], float r_no[3], int *r_index,
|
||||
struct Object **r_ob, float r_obmat[4][4]) RET_ZERO
|
||||
|
||||
void ED_lattice_editlatt_make(struct Object *obedit) RET_NONE
|
||||
|
|
Loading…
Reference in New Issue