Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2016-07-18 12:25:44 +0300
committerCampbell Barton <ideasman42@gmail.com>2016-07-18 12:25:44 +0300
commit9186b9ae4806f4bbc1a14417c408e844f8e8cc1a (patch)
tree117bbd4ace75825e3a65f0ba2a447509bde0df85 /source/blender/editors
parentcfbd605567f48229a923df382baf6db98fbafc61 (diff)
parent9946cca14676bf07b3c7c103e99033fe1e4e423e (diff)
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/armature/armature_utils.c12
-rw-r--r--source/blender/editors/include/ED_keyframing.h8
-rw-r--r--source/blender/editors/include/ED_view3d.h2
-rw-r--r--source/blender/editors/interface/interface.c2
-rw-r--r--source/blender/editors/interface/interface_handlers.c170
-rw-r--r--source/blender/editors/interface/interface_icons.c30
-rw-r--r--source/blender/editors/interface/interface_ops.c2
-rw-r--r--source/blender/editors/interface/interface_regions.c2
-rw-r--r--source/blender/editors/interface/interface_templates.c4
-rw-r--r--source/blender/editors/mesh/editmesh_intersect.c2
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c2
-rw-r--r--source/blender/editors/object/object_group.c2
-rw-r--r--source/blender/editors/object/object_relations.c10
-rw-r--r--source/blender/editors/object/object_select.c1
-rw-r--r--source/blender/editors/object/object_vgroup.c6
-rw-r--r--source/blender/editors/render/render_internal.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c8
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c29
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c10
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c25
-rw-r--r--source/blender/editors/space_clip/clip_editor.c2
-rw-r--r--source/blender/editors/space_graph/graph_draw.c2
-rw-r--r--source/blender/editors/space_image/image_ops.c172
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c194
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c19
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h1
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c55
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c68
-rw-r--r--source/blender/editors/transform/transform_snap_object.c1316
32 files changed, 1348 insertions, 820 deletions
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index 6306926e0b2..6979a324b69 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -424,7 +424,9 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
for (curBone = bones->first; curBone; curBone = curBone->next) {
eBone = MEM_callocN(sizeof(EditBone), "make_editbone");
- /* Copy relevant data from bone to eBone */
+ /* Copy relevant data from bone to eBone
+ * Keep selection logic in sync with ED_armature_sync_selection.
+ */
eBone->parent = parent;
BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name));
eBone->flag = curBone->flag;
@@ -435,11 +437,11 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
eBone->flag |= BONE_TIPSEL;
if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
eBone->parent->flag |= BONE_TIPSEL;
- eBone->flag &= ~BONE_ROOTSEL; /* this is ignored when there is a connected parent, so unset it */
- }
- else {
- eBone->flag |= BONE_ROOTSEL;
}
+
+ /* For connected bones, take care when changing the selection when we have a connected parent,
+ * this flag is a copy of '(eBone->parent->flag & BONE_TIPSEL)'. */
+ eBone->flag |= BONE_ROOTSEL;
}
else {
/* if the bone is not selected, but connected to its parent
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index 81e2558e765..602e203a381 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -325,18 +325,18 @@ bool ANIM_driver_vars_paste(struct ReportList *reports, struct FCurve *fcu, bool
/* Notes:
* - All the defines for this (User-Pref settings and Per-Scene settings)
* are defined in DNA_userdef_types.h
- * - Scene settings take presidence over those for userprefs, with old files
+ * - Scene settings take precedence over those for userprefs, with old files
* inheriting userpref settings for the scene settings
* - "On/Off + Mode" are stored per Scene, but "settings" are currently stored
* as userprefs
*/
/* Auto-Keying macros for use by various tools */
-/* check if auto-keyframing is enabled (per scene takes presidence) */
+/* check if auto-keyframing is enabled (per scene takes precedence) */
#define IS_AUTOKEY_ON(scene) ((scene) ? (scene->toolsettings->autokey_mode & AUTOKEY_ON) : (U.autokey_mode & AUTOKEY_ON))
-/* check the mode for auto-keyframing (per scene takes presidence) */
+/* check the mode for auto-keyframing (per scene takes precedence) */
#define IS_AUTOKEY_MODE(scene, mode) ((scene) ? (scene->toolsettings->autokey_mode == AUTOKEY_MODE_##mode) : (U.autokey_mode == AUTOKEY_MODE_##mode))
-/* check if a flag is set for auto-keyframing (per scene takes presidence) */
+/* check if a flag is set for auto-keyframing (per scene takes precedence) */
#define IS_AUTOKEY_FLAG(scene, flag) \
((scene) ? \
((scene->toolsettings->autokey_flag & AUTOKEY_FLAG_##flag) || (U.autokey_flag & AUTOKEY_FLAG_##flag)) \
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index b09284aa759..48c1e2d1996 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -208,6 +208,7 @@ eV3DProjStatus ED_view3d_project_float_global(const struct ARegion *ar, const fl
eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag);
float ED_view3d_calc_zfac(const struct RegionView3D *rv3d, const float co[3], bool *r_flip);
+bool ED_view3d_clip_segment(const struct RegionView3D *rv3d, float ray_start[3], float ray_end[3]);
bool ED_view3d_win_to_ray(
const struct ARegion *ar, const struct View3D *v3d, const float mval[2],
float ray_start[3], float ray_normal[3], const bool do_clip);
@@ -218,6 +219,7 @@ void ED_view3d_global_to_vector(const struct RegionView3D *rv3d, const float coo
void ED_view3d_win_to_3d(const struct ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]);
void ED_view3d_win_to_3d_int(const struct ARegion *ar, const float depth_pt[3], const int mval[2], float out[3]);
void ED_view3d_win_to_delta(const struct ARegion *ar, const float mval[2], float out[3], const float zfac);
+void ED_view3d_win_to_origin(const struct ARegion *ar, const float mval[2], float out[3]);
void ED_view3d_win_to_vector(const struct ARegion *ar, const float mval[2], float out[3]);
bool ED_view3d_win_to_segment(const struct ARegion *ar, struct View3D *v3d, const float mval[2],
float r_ray_start[3], float r_ray_end[3], const bool do_clip);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index ba7240be5d8..cbe8654ceb6 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1138,7 +1138,7 @@ static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but,
* as new items are added to the menu later on. It also optimises efficiency -
* a radial menu is best kept symmetrical, with as large an angle between
* items as possible, so that the gestural mouse movements can be fast and inexact.
-
+ *
* It starts off with two opposite sides for the first two items
* then joined by the one below for the third (this way, even with three items,
* the menu seems to still be 'in order' reading left to right). Then the fourth is
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 0a0ecf93d17..11703208b2a 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -1057,7 +1057,9 @@ static void ui_multibut_free(uiHandleButtonData *data, uiBlock *block)
}
}
-static bool ui_multibut_states_tag(uiBut *but_active, uiHandleButtonData *data, const wmEvent *event)
+static bool ui_multibut_states_tag(
+ uiBut *but_active,
+ uiHandleButtonData *data, const wmEvent *event)
{
uiBut *but;
float seg[2][2];
@@ -1668,7 +1670,9 @@ static bool ui_but_contains_point_px_icon(uiBut *but, ARegion *ar, const wmEvent
return BLI_rcti_isect_pt(&rect, x, y);
}
-static bool ui_but_drag_init(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static bool ui_but_drag_init(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
/* prevent other WM gestures to start while we try to drag */
WM_gestures_remove(C);
@@ -1740,11 +1744,16 @@ static bool ui_but_drag_init(bContext *C, uiBut *but, uiHandleButtonData *data,
}
}
else {
- wmDrag *drag;
+ wmDrag *drag = WM_event_start_drag(
+ C, but->icon, but->dragtype, but->dragpoin,
+ ui_but_value_get(but), WM_DRAG_NOP);
- drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_but_value_get(but), WM_DRAG_NOP);
- if (but->imb)
- WM_event_drag_image(drag, but->imb, but->imb_scale, BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect));
+ if (but->imb) {
+ WM_event_drag_image(
+ drag, but->imb, but->imb_scale,
+ BLI_rctf_size_x(&but->rect),
+ BLI_rctf_size_y(&but->rect));
+ }
}
return true;
}
@@ -1872,11 +1881,15 @@ static void ui_but_smart_controller_add(bContext *C, uiBut *from, uiBut *to)
/* (3) add a new controller */
if (WM_operator_name_call(C, "LOGIC_OT_controller_add", WM_OP_EXEC_DEFAULT, &props_ptr) & OPERATOR_FINISHED) {
cont = (bController *)ob->controllers.last;
- cont->type = CONT_LOGIC_AND; /* Quick fix to make sure we always have an AND controller. It might be nicer to make sure the operator gives us the right one though... */
+ /* Quick fix to make sure we always have an AND controller.
+ * It might be nicer to make sure the operator gives us the right one though... */
+ cont->type = CONT_LOGIC_AND;
/* (4) link the sensor->controller->actuator */
tmp_but = MEM_callocN(sizeof(uiBut), "uiBut");
- UI_but_link_set(tmp_but, (void **)&cont, (void ***)&(cont->links), &(cont->totlinks), from->link->tocode, (int)to->hardmin);
+ UI_but_link_set(
+ tmp_but, (void **)&cont, (void ***)&(cont->links),
+ &cont->totlinks, from->link->tocode, (int)to->hardmin);
tmp_but->hardmin = from->link->tocode;
tmp_but->poin = (char *)cont;
@@ -3180,7 +3193,9 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
}
-static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static void ui_do_but_textedit(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int retval = WM_UI_HANDLER_CONTINUE;
bool changed = false, inbox = false, update = false;
@@ -3233,7 +3248,8 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
if (data->searchbox)
inbox = ui_searchbox_inside(data->searchbox, event->x, event->y);
- /* for double click: we do a press again for when you first click on button (selects all text, no cursor pos) */
+ /* for double click: we do a press again for when you first click on button
+ * (selects all text, no cursor pos) */
if (event->val == KM_PRESS || event->val == KM_DBL_CLICK) {
float mx, my;
@@ -3477,7 +3493,9 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
ED_region_tag_redraw(data->region);
}
-static void ui_do_but_textedit_select(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static void ui_do_but_textedit_select(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my, retval = WM_UI_HANDLER_CONTINUE;
@@ -3682,7 +3700,9 @@ static uiBut *ui_but_list_row_text_activate(
/* ***************** events for different button types *************** */
-static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_BUT(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
@@ -3713,7 +3733,9 @@ static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, cons
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_HOTKEYEVT(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
@@ -3776,7 +3798,9 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_KEYEVT(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
@@ -3802,7 +3826,9 @@ static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, c
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_TEX(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS) {
@@ -3830,7 +3856,9 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_SEARCH_UNLINK(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
uiButExtraIconType extra_icon_type;
@@ -3877,7 +3905,9 @@ static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHa
return ui_do_but_TEX(C, block, but, data, event);
}
-static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_TOG(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
#ifdef USE_DRAG_TOGGLE
if (data->state == BUTTON_STATE_HIGHLIGHT) {
@@ -3944,7 +3974,9 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_EXIT(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
@@ -4092,7 +4124,7 @@ static float ui_numedit_apply_snap(
static bool ui_numedit_but_NUM(
uiBut *but, uiHandleButtonData *data,
- int mx,
+ int mx, const bool is_motion,
const enum eSnapType snap, float fac)
{
float deler, tempf, softmin, softmax, softrange;
@@ -4100,8 +4132,10 @@ static bool ui_numedit_but_NUM(
bool changed = false;
const bool is_float = ui_but_is_float(but);
- /* prevent unwanted drag adjustments */
- if (ui_but_dragedit_update_mval(data, mx) == false) {
+ /* prevent unwanted drag adjustments, test motion so modifier keys refresh. */
+ if ((is_motion || data->draglock) &&
+ (ui_but_dragedit_update_mval(data, mx) == false))
+ {
return changed;
}
@@ -4242,7 +4276,9 @@ static bool ui_numedit_but_NUM(
return changed;
}
-static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_NUM(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my; /* mouse location scaled to fit the UI */
int screen_mx, screen_my; /* mouse location kept at screen pixel coords */
@@ -4324,6 +4360,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
}
}
else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
+ const bool is_motion = (event->type == MOUSEMOVE);
const enum eSnapType snap = ui_event_to_snap(event);
float fac;
@@ -4335,8 +4372,9 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
fac = 1.0f;
if (event->shift) fac /= 10.0f;
- if (ui_numedit_but_NUM(but, data, (ui_but_is_cursor_warp(but) ? screen_mx : mx), snap, fac))
+ if (ui_numedit_but_NUM(but, data, (ui_but_is_cursor_warp(but) ? screen_mx : mx), is_motion, snap, fac)) {
ui_numedit_apply(C, block, but, data);
+ }
#ifdef USE_DRAG_MULTINUM
else if (data->multi_data.has_mbuts) {
if (data->multi_data.init == BUTTON_MULTI_INIT_ENABLE) {
@@ -4430,7 +4468,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
static bool ui_numedit_but_SLI(
uiBut *but, uiHandleButtonData *data,
- int mx, const bool is_horizontal,
+ int mx, const bool is_horizontal, const bool is_motion,
const bool snap, const bool shift)
{
float deler, f, tempf, softmin, softmax, softrange;
@@ -4440,8 +4478,9 @@ static bool ui_numedit_but_SLI(
/* note, 'offs' is really from the widget drawing rounded corners see 'widget_numslider' */
float offs;
- /* prevent unwanted drag adjustments */
+ /* prevent unwanted drag adjustments, test motion so modifier keys refresh. */
if ((but->type != UI_BTYPE_SCROLL) &&
+ (is_motion || data->draglock) &&
(ui_but_dragedit_update_mval(data, mx) == false))
{
return changed;
@@ -4541,7 +4580,9 @@ static bool ui_numedit_but_SLI(
return changed;
}
-static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_SLI(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my, click = 0;
int retval = WM_UI_HANDLER_CONTINUE;
@@ -4634,12 +4675,14 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
}
}
else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
+ const bool is_motion = (event->type == MOUSEMOVE);
#ifdef USE_DRAG_MULTINUM
data->multi_data.drag_dir[0] += abs(data->draglastx - mx);
data->multi_data.drag_dir[1] += abs(data->draglasty - my);
#endif
- if (ui_numedit_but_SLI(but, data, mx, true, event->ctrl != 0, event->shift != 0))
+ if (ui_numedit_but_SLI(but, data, mx, true, is_motion, event->ctrl != 0, event->shift != 0)) {
ui_numedit_apply(C, block, but, data);
+ }
#ifdef USE_DRAG_MULTINUM
else if (data->multi_data.has_mbuts) {
@@ -4722,7 +4765,9 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
return retval;
}
-static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_SCROLL(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my /*, click = 0 */;
int retval = WM_UI_HANDLER_CONTINUE;
@@ -4765,8 +4810,10 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
else if (event->type == MOUSEMOVE) {
- if (ui_numedit_but_SLI(but, data, (horizontal) ? mx : my, horizontal, false, false))
+ const bool is_motion = (event->type == MOUSEMOVE);
+ if (ui_numedit_but_SLI(but, data, (horizontal) ? mx : my, horizontal, is_motion, false, false)) {
ui_numedit_apply(C, block, but, data);
+ }
}
retval = WM_UI_HANDLER_BREAK;
@@ -4775,7 +4822,9 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
return retval;
}
-static int ui_do_but_GRIP(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_GRIP(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
int retval = WM_UI_HANDLER_CONTINUE;
@@ -4826,7 +4875,9 @@ static int ui_do_but_GRIP(bContext *C, uiBlock *block, uiBut *but, uiHandleButto
return retval;
}
-static int ui_do_but_LISTROW(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_LISTROW(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
/* hack to pass on ctrl+click and double click to overlapping text
@@ -4846,7 +4897,9 @@ static int ui_do_but_LISTROW(bContext *C, uiBut *but, uiHandleButtonData *data,
return ui_do_but_EXIT(C, but, data, event);
}
-static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_BLOCK(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
@@ -5021,7 +5074,9 @@ static void ui_palette_set_active(uiBut *but)
}
}
-static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_COLOR(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
/* first handle click on icondrag type button */
@@ -5154,7 +5209,9 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_UNITVEC(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_UNITVEC(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -5431,7 +5488,9 @@ static void ui_ndofedit_but_HSVCUBE(
ui_but_v3_set(but, data->vec);
}
-static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_HSVCUBE(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -5693,7 +5752,9 @@ static void ui_ndofedit_but_HSVCIRCLE(
}
-static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_HSVCIRCLE(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
ColorPicker *cpicker = but->custom_data;
float *hsv = cpicker->color_data;
@@ -5821,7 +5882,9 @@ static bool ui_numedit_but_COLORBAND(uiBut *but, uiHandleButtonData *data, int m
return changed;
}
-static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_COLORBAND(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
ColorBand *coba;
CBData *cbd;
@@ -5997,7 +6060,9 @@ static bool ui_numedit_but_CURVE(
return changed;
}
-static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_CURVE(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my, a;
bool changed = false;
@@ -6165,7 +6230,9 @@ static bool ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int m
return changed;
}
-static int ui_do_but_HISTOGRAM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_HISTOGRAM(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -6238,7 +6305,9 @@ static bool ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx
return changed;
}
-static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_WAVEFORM(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -6292,7 +6361,9 @@ static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleB
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_LINK(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
VECCOPY2D(but->linkto, event->mval);
@@ -6355,7 +6426,9 @@ static bool ui_numedit_but_TRACKPREVIEW(
return changed;
}
-static int ui_do_but_TRACKPREVIEW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_TRACKPREVIEW(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -6851,7 +6924,8 @@ static bool ui_but_menu(bContext *C, uiBut *but)
WM_operator_properties_create(&ptr_props, "WM_OT_doc_view");
RNA_string_set(&ptr_props, "doc_id", buf);
- uiItemFullO(layout, "WM_OT_doc_view", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"),
+ uiItemFullO(layout, "WM_OT_doc_view",
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"),
ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
/* XXX inactive option, not for public! */
@@ -6860,7 +6934,8 @@ static bool ui_but_menu(bContext *C, uiBut *but)
RNA_string_set(&ptr_props, "doc_id", buf);
RNA_string_set(&ptr_props, "doc_new", RNA_property_description(but->rnaprop));
- uiItemFullO(layout, "WM_OT_doc_edit", "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0);
+ uiItemFullO(layout, "WM_OT_doc_edit",
+ "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0);
#endif
}
}
@@ -7440,7 +7515,8 @@ static bool ui_but_contains_point_px(ARegion *ar, uiBut *but, int x, int y)
/**
* Can we mouse over the button or is it hidden/disabled/layout.
- * Note: ctrl is kind of a hack currently, so that non-embossed UI_BTYPE_TEXT button behaves as a label when ctrl is not pressed.
+ * \note ctrl is kind of a hack currently,
+ * so that non-embossed UI_BTYPE_TEXT button behaves as a label when ctrl is not pressed.
*/
static bool ui_but_is_interactive(const uiBut *but, const bool labeledit)
{
@@ -7634,7 +7710,9 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
if (but->block->auto_open == true) { /* test for toolbox */
time = 1;
}
- else if ((but->block->flag & UI_BLOCK_LOOP && but->type != UI_BTYPE_BLOCK) || but->block->auto_open == true) {
+ else if ((but->block->flag & UI_BLOCK_LOOP && but->type != UI_BTYPE_BLOCK) ||
+ (but->block->auto_open == true))
+ {
time = 5 * U.menuthreshold2;
}
else if (U.uiflag & USER_MENUOPENAUTO) {
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index c1d7a9ada96..3660160a98c 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -1061,6 +1061,9 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size)
}
}
+static void ui_id_preview_image_render_size(
+ const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job);
+
void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool big)
{
Icon *icon = BKE_icon_get(icon_id);
@@ -1076,22 +1079,19 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi
}
if (di) {
- if (di->type == ICON_TYPE_PREVIEW) {
- PreviewImage *prv = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
-
- if (prv) {
- const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON;
-
- if (!prv->use_deferred || prv->rect[size] || (prv->flag[size] & PRV_USER_EDITED)) {
- return;
+ switch (di->type) {
+ case ICON_TYPE_PREVIEW:
+ {
+ ID *id = (icon->type != 0) ? icon->obj : NULL;
+ PreviewImage *prv = id ? BKE_previewimg_id_ensure(id) : icon->obj;
+
+ if (prv) {
+ const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON;
+
+ if (id || prv->use_deferred) {
+ ui_id_preview_image_render_size(C, NULL, id, prv, size, true);
+ }
}
-
- icon_create_rect(prv, size);
-
- /* Always using job (background) version. */
- ED_preview_icon_job(C, prv, NULL, prv->rect[size], prv->w[size], prv->h[size]);
-
- prv->flag[size] &= ~PRV_CHANGED;
}
}
}
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 01b10b7b032..1af6d902b18 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -416,7 +416,7 @@ bool UI_context_copy_to_selected_list(
if ((id_data == NULL) ||
(id_data->tag & LIB_TAG_DOIT) == 0 ||
- ID_IS_LINKED_DATABLOCK(id_data->lib) ||
+ ID_IS_LINKED_DATABLOCK(id_data) ||
(GS(id_data->name) != id_code))
{
BLI_remlink(&lb, link);
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 575b32e81e8..d4205c50ddc 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -110,7 +110,7 @@ bool ui_but_menu_step_poll(const uiBut *but)
{
BLI_assert(but->type == UI_BTYPE_MENU);
- /* currenly only RNA buttons */
+ /* currently only RNA buttons */
return ((but->menu_step_func != NULL) ||
(but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM));
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 7cc7b540cc0..3af25ba8894 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -301,7 +301,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
break;
case UI_ID_LOCAL:
if (id) {
- if (id_make_local(CTX_data_main(C), id, false)) {
+ if (id_make_local(CTX_data_main(C), id, false, false)) {
/* reassign to get get proper updates/notifiers */
idptr = RNA_property_pointer_get(&template->ptr, template->prop);
RNA_property_pointer_set(&template->ptr, template->prop, idptr);
@@ -453,7 +453,7 @@ static void template_ID(
else {
but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y,
NULL, 0, 0, 0, 0, TIP_("Direct linked library datablock, click to make local"));
- if (!id_make_local(CTX_data_main(C), id, true /* test */) || (idfrom && idfrom->lib))
+ if (!id_make_local(CTX_data_main(C), id, true /* test */, false) || (idfrom && idfrom->lib))
UI_but_flag_enable(but, UI_BUT_DISABLED);
}
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index 69588928253..281a8b2a02d 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -563,7 +563,7 @@ static BMEdge *bm_face_split_edge_find(
if (UNLIKELY(BM_edge_exists(v_pivot, l_iter->e->v1) ||
BM_edge_exists(v_pivot, l_iter->e->v2)))
{
- /* very unlikley but will cause complications splicing the verts together,
+ /* very unlikely but will cause complications splicing the verts together,
* so just skip this case */
ok = false;
}
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index e3e5863dc0e..2cdb00286aa 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -395,7 +395,7 @@ static void edbm_ripsel_deselect_helper(BMesh *bm, EdgeLoopPair *eloop_pairs,
* return an un-ordered array of loop pairs
* use for rebuilding face-fill
*
- * \note the method currenly used fails for edges with 3+ face users and gives
+ * \note the method currently used fails for edges with 3+ face users and gives
* nasty holes in the mesh, there isnt a good way of knowing ahead of time
* which loops will be split apart (its possible to figure out but quite involved).
* So for now this is a known limitation of current rip-fill option.
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index bcdd170c53c..0fe43c44d7d 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -440,7 +440,7 @@ static int group_link_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
/* Early return check, if the object is already in group
- * we could sckip all the dependency check and just consider
+ * we could skip all the dependency check and just consider
* operator is finished.
*/
if (BKE_group_object_exists(group, ob)) {
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 55eb30ac2de..d8b0767562c 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -2103,11 +2103,11 @@ static void make_local_makelocalmaterial(Material *ma)
AnimData *adt;
int b;
- id_make_local(G.main, &ma->id, false);
+ id_make_local(G.main, &ma->id, false, false);
for (b = 0; b < MAX_MTEX; b++)
if (ma->mtex[b] && ma->mtex[b]->tex)
- id_make_local(G.main, &ma->mtex[b]->tex->id, false);
+ id_make_local(G.main, &ma->mtex[b]->tex->id, false, false);
adt = BKE_animdata_from_id(&ma->id);
if (adt) BKE_animdata_make_local(adt);
@@ -2235,7 +2235,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
}
if (ob->id.lib)
- id_make_local(bmain, &ob->id, false);
+ id_make_local(bmain, &ob->id, false, false);
}
CTX_DATA_END;
@@ -2257,7 +2257,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
id = ob->data;
if (id && (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL))) {
- id_make_local(bmain, id, false);
+ id_make_local(bmain, id, false, false);
adt = BKE_animdata_from_id(id);
if (adt) BKE_animdata_make_local(adt);
@@ -2289,7 +2289,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
for (b = 0; b < MAX_MTEX; b++)
if (la->mtex[b] && la->mtex[b]->tex)
- id_make_local(bmain, &la->mtex[b]->tex->id, false);
+ id_make_local(bmain, &la->mtex[b]->tex->id, false, false);
}
else {
for (a = 0; a < ob->totcol; a++) {
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 8501cea4e00..7db32957b42 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -538,7 +538,6 @@ static bool select_grouped_parent(bContext *C) /* Makes parent active and de-sel
/* can be NULL if parent in other scene */
if (baspar && BASE_SELECTABLE(v3d, baspar)) {
- ED_base_object_select(basact, BA_DESELECT);
ED_base_object_select(baspar, BA_SELECT);
ED_base_object_activate(C, baspar);
changed = true;
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 6e8aaebcccc..ad41fb23a69 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -3538,8 +3538,10 @@ static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr)
return BLI_natstrcmp(def_a->name, def_b->name);
}
-/* Sorts the weight groups according to the bone hierarchy of the
- associated armature (similar to how bones are ordered in the Outliner) */
+/**
+ * Sorts the weight groups according to the bone hierarchy of the
+ * associated armature (similar to how bones are ordered in the Outliner)
+ */
static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase)
{
if (bonebase == NULL) {
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 1203889cf0e..8c5d25ad44d 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -1482,7 +1482,7 @@ static void render_view3d_do(RenderEngine *engine, const bContext *C)
void render_view3d_update(RenderEngine *engine, const bContext *C)
{
/* this shouldn't be needed and causes too many database rebuilds, but we
- * aren't actually tracking updates for all relevent datablocks so this is
+ * aren't actually tracking updates for all relevant datablocks so this is
* a catch-all for updates */
engine->update_flag |= RE_ENGINE_UPDATE_DATABASE;
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 6ed969cb270..d60c8e8dbd9 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -183,8 +183,8 @@ BLI_INLINE unsigned char f_to_char(const float val)
/* to avoid locking in tile initialization */
#define TILE_PENDING SET_INT_IN_POINTER(-1)
-/* This is mainly a convenience struct used so we can keep an array of images we use
- * Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread
+/* This is mainly a convenience struct used so we can keep an array of images we use -
+ * their imbufs, etc, in 1 array, When using threads this array is copied for each thread
* because 'partRedrawRect' and 'touch' values would not be thread safe */
typedef struct ProjPaintImage {
Image *ima;
@@ -202,7 +202,7 @@ typedef struct ProjPaintImage {
*/
typedef struct ProjStrokeHandle {
/* Support for painting from multiple views at once,
- * currently used to impliment symmetry painting,
+ * currently used to implement symmetry painting,
* we can assume at least the first is set while painting. */
struct ProjPaintState *ps_views[8];
int ps_views_tot;
@@ -2174,7 +2174,7 @@ static void project_bucket_clip_face(
if ((*tot) < 3) {
/* no intersections to speak of, but more probable is that all face is just outside the
- * rectangle and culled due to float precision issues. Since above teste have failed,
+ * rectangle and culled due to float precision issues. Since above tests have failed,
* just dump triangle as is for painting */
*tot = 0;
copy_v2_v2(bucket_bounds_uv[*tot], uv1co); (*tot)++;
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index aa17cb02fe5..1431958501d 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -491,31 +491,30 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float
}
/* Returns zero if no sculpt changes should be made, non-zero otherwise */
-static int paint_smooth_stroke(PaintStroke *stroke, float output[2], float *outpressure,
- const PaintSample *sample, PaintMode mode)
+static bool paint_smooth_stroke(
+ PaintStroke *stroke, const PaintSample *sample, PaintMode mode,
+ float r_mouse[2], float *r_pressure)
{
if (paint_supports_smooth_stroke(stroke->brush, mode)) {
float radius = stroke->brush->smooth_stroke_radius * stroke->zoom_2d;
- float u = stroke->brush->smooth_stroke_factor, v = 1.0f - u;
- float dx = stroke->last_mouse_position[0] - sample->mouse[0];
- float dy = stroke->last_mouse_position[1] - sample->mouse[1];
+ float u = stroke->brush->smooth_stroke_factor;
/* If the mouse is moving within the radius of the last move,
* don't update the mouse position. This allows sharp turns. */
- if (dx * dx + dy * dy < radius * radius)
- return 0;
+ if (len_squared_v2v2(stroke->last_mouse_position, sample->mouse) < SQUARE(radius)) {
+ return false;
+ }
- output[0] = sample->mouse[0] * v + stroke->last_mouse_position[0] * u;
- output[1] = sample->mouse[1] * v + stroke->last_mouse_position[1] * u;
- *outpressure = sample->pressure * v + stroke->last_pressure * u;
+ interp_v2_v2v2(r_mouse, sample->mouse, stroke->last_mouse_position, u);
+ *r_pressure = interpf(sample->pressure, stroke->last_pressure, u);
}
else {
- output[0] = sample->mouse[0];
- output[1] = sample->mouse[1];
- *outpressure = sample->pressure;
+ r_mouse[0] = sample->mouse[0];
+ r_mouse[1] = sample->mouse[1];
+ *r_pressure = sample->pressure;
}
- return 1;
+ return true;
}
static float paint_space_stroke_spacing(const Scene *scene, PaintStroke *stroke, float size_pressure, float spacing_pressure)
@@ -1190,7 +1189,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* airbrush */
((br->flag & BRUSH_AIRBRUSH) && event->type == TIMER && event->customdata == stroke->timer))
{
- if (paint_smooth_stroke(stroke, mouse, &pressure, &sample_average, mode)) {
+ if (paint_smooth_stroke(stroke, &sample_average, mode, mouse, &pressure)) {
if (stroke->stroke_started) {
if (paint_space_stroke_enabled(br, mode)) {
if (paint_space_stroke(C, op, mouse, pressure))
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index e874a969963..f21f62cc141 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -2379,9 +2379,8 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
swap_m4m4(vc->rv3d->persmat, mat);
/* calculate pivot for rotation around seletion if needed */
- if (U.uiflag & USER_ORBIT_SELECTION) {
- paint_last_stroke_update(scene, vc->ar, mval);
- }
+ /* also needed for "View Selected" on last stroke */
+ paint_last_stroke_update(scene, vc->ar, mval);
DAG_id_tag_update(ob->data, 0);
ED_region_tag_redraw(vc->ar);
@@ -2842,9 +2841,8 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
}
/* calculate pivot for rotation around seletion if needed */
- if (U.uiflag & USER_ORBIT_SELECTION) {
- paint_last_stroke_update(scene, vc->ar, mval);
- }
+ /* also needed for "View Selected" on last stroke */
+ paint_last_stroke_update(scene, vc->ar, mval);
ED_region_tag_redraw(vc->ar);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index cc7531b9783..1305b76b5ad 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1145,7 +1145,9 @@ static void calc_area_normal_and_center(
/* Return modified brush strength. Includes the direction of the brush, positive
* values pull vertices, negative values push. Uses tablet pressure and a
* special multiplier found experimentally to scale the strength factor. */
-static float brush_strength(const Sculpt *sd, const StrokeCache *cache, const float feather, const UnifiedPaintSettings *ups)
+static float brush_strength(
+ const Sculpt *sd, const StrokeCache *cache,
+ const float feather, const UnifiedPaintSettings *ups)
{
const Scene *scene = cache->vc->scene;
const Brush *brush = BKE_paint_brush((Paint *)&sd->paint);
@@ -3985,7 +3987,9 @@ static void sculpt_init_mirror_clipping(Object *ob, SculptSession *ss)
}
/* Initialize the stroke cache invariants from operator properties */
-static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, const float mouse[2])
+static void sculpt_update_cache_invariants(
+ bContext *C, Sculpt *sd, SculptSession *ss,
+ wmOperator *op, const float mouse[2])
{
StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
Scene *scene = CTX_data_scene(C);
@@ -4448,7 +4452,9 @@ static void sculpt_raycast_detail_cb(PBVHNode *node, void *data_v, float *tmin)
}
}
-static float sculpt_raycast_init(ViewContext *vc, const float mouse[2], float ray_start[3], float ray_end[3], float ray_normal[3], bool original)
+static float sculpt_raycast_init(
+ ViewContext *vc, const float mouse[2],
+ float ray_start[3], float ray_end[3], float ray_normal[3], bool original)
{
float obimat[4][4];
float dist;
@@ -4956,8 +4962,9 @@ void sculpt_dyntopo_node_layers_add(SculptSession *ss)
cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_INT, layer_id);
}
- ss->cd_vert_node_offset = CustomData_get_n_offset(&ss->bm->vdata, CD_PROP_INT,
- cd_node_layer_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_INT));
+ ss->cd_vert_node_offset = CustomData_get_n_offset(
+ &ss->bm->vdata, CD_PROP_INT,
+ cd_node_layer_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_INT));
ss->bm->vdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY;
@@ -4967,8 +4974,9 @@ void sculpt_dyntopo_node_layers_add(SculptSession *ss)
cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->pdata, CD_PROP_INT, layer_id);
}
- ss->cd_face_node_offset = CustomData_get_n_offset(&ss->bm->pdata, CD_PROP_INT,
- cd_node_layer_index - CustomData_get_layer_index(&ss->bm->pdata, CD_PROP_INT));
+ ss->cd_face_node_offset = CustomData_get_n_offset(
+ &ss->bm->pdata, CD_PROP_INT,
+ cd_node_layer_index - CustomData_get_layer_index(&ss->bm->pdata, CD_PROP_INT));
ss->bm->pdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY;
}
@@ -5667,7 +5675,8 @@ static void SCULPT_OT_sample_detail_size(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_int_array(ot->srna, "location", 2, NULL, 0, SHRT_MAX, "Location", "Screen Coordinates of sampling", 0, SHRT_MAX);
+ RNA_def_int_array(ot->srna, "location", 2, NULL, 0, SHRT_MAX,
+ "Location", "Screen Coordinates of sampling", 0, SHRT_MAX);
}
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 1ff656243d6..14d0f909d23 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -634,7 +634,7 @@ typedef struct PrefetchQueue {
short render_size, render_flag;
/* If true prefecthing goes forward in time,
- * othwewise it goes backwards in time (starting from current frame).
+ * otherwise it goes backwards in time (starting from current frame).
*/
bool forward;
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index b837e516422..ae91a466495 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -826,7 +826,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
//if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0)
// return;
- /* No curve to modify/visualise the result?
+ /* No curve to modify/visualize the result?
* => We still want to show the 1-1 default...
*/
if ((fcu->totvert == 0) && BLI_listbase_is_empty(&fcu->modifiers)) {
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 06caf930988..1538842b139 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1061,6 +1061,12 @@ typedef struct ImageOpenData {
ImageFormatData im_format;
} ImageOpenData;
+typedef struct ImageFrameRange {
+ struct ImageFrameRange *next, *prev;
+ ListBase frames;
+ char filepath[FILE_MAX];
+} ImageFrameRange;
+
typedef struct ImageFrame {
struct ImageFrame *next, *prev;
int framenr;
@@ -1086,10 +1092,10 @@ static void image_open_cancel(bContext *UNUSED(C), wmOperator *op)
* \param frames [out] the list of frame numbers found in the files matching the first one by name
* \param path [out] the full path of the first file in the list of image files
*/
-static void image_sequence_get_frames(PointerRNA *ptr, ListBase *frames, char *path, const size_t maxlen)
+static void image_sequence_get_frame_ranges(PointerRNA *ptr, ListBase *frames_all)
{
char dir[FILE_MAXDIR];
- bool is_first_entry = true;
+ ImageFrameRange *frame_range = NULL;
RNA_string_get(ptr, "directory", dir);
RNA_BEGIN (ptr, itemptr, "files")
@@ -1101,29 +1107,26 @@ static void image_sequence_get_frames(PointerRNA *ptr, ListBase *frames, char *p
ImageFrame *frame = MEM_callocN(sizeof(ImageFrame), "image_frame");
/* use the first file in the list as base filename */
- if (is_first_entry) {
- BLI_join_dirfile(path, maxlen, dir, filename);
- frame->framenr = BLI_stringdec(filename, base_head, base_tail, &digits);
- BLI_addtail(frames, frame);
- is_first_entry = false;
+ frame->framenr = BLI_stringdec(filename, head, tail, &digits);
+
+ /* still in the same sequence */
+ if ((frame_range != NULL) &&
+ (STREQLEN(base_head, head, FILE_MAX)) &&
+ (STREQLEN(base_tail, tail, FILE_MAX)))
+ {
+ /* pass */
}
else {
- frame->framenr = BLI_stringdec(filename, head, tail, &digits);
+ /* start a new frame range */
+ frame_range = MEM_callocN(sizeof(*frame_range), __func__);
+ BLI_join_dirfile(frame_range->filepath, sizeof(frame_range->filepath), dir, filename);
+ BLI_addtail(frames_all, frame_range);
- /* still in the same sequence */
- if ((STREQLEN(base_head, head, FILE_MAX)) &&
- (STREQLEN(base_tail, tail, FILE_MAX)))
- {
- BLI_addtail(frames, frame);
- }
- else {
- /* different file base name found, is ignored */
- MEM_freeN(filename);
- MEM_freeN(frame);
- break;
- }
+ BLI_strncpy(base_head, head, sizeof(base_head));
+ BLI_strncpy(base_tail, tail, sizeof(base_tail));
}
+ BLI_addtail(&frame_range->frames, frame);
MEM_freeN(filename);
}
RNA_END
@@ -1164,6 +1167,52 @@ static int image_sequence_get_len(ListBase *frames, int *ofs)
return 0;
}
+static Image *image_open_single(
+ wmOperator *op, const char *filepath, const char *relbase,
+ bool is_relative_path, bool use_multiview, int frame_seq_len)
+{
+ bool exists = false;
+ Image *ima = NULL;
+
+ errno = 0;
+ ima = BKE_image_load_exists_ex(filepath, &exists);
+
+ if (!ima) {
+ if (op->customdata) MEM_freeN(op->customdata);
+ BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s",
+ filepath, errno ? strerror(errno) : TIP_("unsupported image format"));
+ return NULL;
+ }
+
+ if (!exists) {
+ /* only image path after save, never ibuf */
+ if (is_relative_path) {
+ BLI_path_rel(ima->name, relbase);
+ }
+
+ /* handle multiview images */
+ if (use_multiview) {
+ ImageOpenData *iod = op->customdata;
+ ImageFormatData *imf = &iod->im_format;
+
+ ima->flag |= IMA_USE_VIEWS;
+ ima->views_format = imf->views_format;
+ *ima->stereo3d_format = imf->stereo3d_format;
+ }
+ else {
+ ima->flag &= ~IMA_USE_VIEWS;
+ BKE_image_free_views(ima);
+ }
+
+ if ((frame_seq_len > 1) && (ima->source == IMA_SRC_FILE)) {
+ ima->source = IMA_SRC_SEQUENCE;
+ }
+ }
+
+ return ima;
+}
+
+
static int image_open_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -1174,70 +1223,60 @@ static int image_open_exec(bContext *C, wmOperator *op)
ImageOpenData *iod = op->customdata;
PointerRNA idptr;
Image *ima = NULL;
- char path[FILE_MAX];
+ char filepath[FILE_MAX];
int frame_seq_len = 0;
int frame_ofs = 1;
- bool exists = false;
const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
+ const bool use_multiview = RNA_boolean_get(op->ptr, "use_multiview");
- RNA_string_get(op->ptr, "filepath", path);
+ if (!op->customdata)
+ image_open_init(C, op);
+
+ RNA_string_get(op->ptr, "filepath", filepath);
if (RNA_struct_property_is_set(op->ptr, "directory") &&
RNA_struct_property_is_set(op->ptr, "files"))
{
- /* only to pass to imbuf */
- char path_full[FILE_MAX];
- BLI_strncpy(path_full, path, sizeof(path_full));
- BLI_path_abs(path_full, G.main->name);
+ bool was_relative = BLI_path_is_rel(filepath);
+ ListBase frame_ranges_all;
- if (!IMB_isanim(path_full)) {
- bool was_relative = BLI_path_is_rel(path);
- ListBase frames;
+ BLI_listbase_clear(&frame_ranges_all);
+ image_sequence_get_frame_ranges(op->ptr, &frame_ranges_all);
+ for (ImageFrameRange *frame_range = frame_ranges_all.first; frame_range; frame_range = frame_range->next) {
+ int frame_range_ofs;
+ int frame_range_seq_len = image_sequence_get_len(&frame_range->frames, &frame_range_ofs);
+ BLI_freelistN(&frame_range->frames);
- BLI_listbase_clear(&frames);
- image_sequence_get_frames(op->ptr, &frames, path, sizeof(path));
- frame_seq_len = image_sequence_get_len(&frames, &frame_ofs);
- BLI_freelistN(&frames);
+ char filepath_range[FILE_MAX];
+ BLI_strncpy(filepath_range, frame_range->filepath, sizeof(filepath_range));
if (was_relative) {
- BLI_path_rel(path, G.main->name);
+ BLI_path_rel(filepath_range, bmain->name);
}
- }
- }
-
- errno = 0;
- ima = BKE_image_load_exists_ex(path, &exists);
+ Image *ima_range = image_open_single(
+ op, filepath_range, bmain->name,
+ is_relative_path, use_multiview, frame_range_seq_len);
- if (!ima) {
- if (op->customdata) MEM_freeN(op->customdata);
- BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s",
- path, errno ? strerror(errno) : TIP_("unsupported image format"));
- return OPERATOR_CANCELLED;
- }
-
- if (!op->customdata)
- image_open_init(C, op);
-
- /* handle multiview images */
- if (RNA_boolean_get(op->ptr, "use_multiview")) {
- ImageFormatData *imf = &iod->im_format;
-
- ima->flag |= IMA_USE_VIEWS;
- ima->views_format = imf->views_format;
- *ima->stereo3d_format = imf->stereo3d_format;
+ /* take the first image */
+ if ((ima == NULL) && ima_range) {
+ ima = ima_range;
+ frame_seq_len = frame_range_seq_len;
+ frame_ofs = frame_range_ofs;
+ }
+ }
+ BLI_freelistN(&frame_ranges_all);
}
else {
- ima->flag &= ~IMA_USE_VIEWS;
- BKE_image_free_views(ima);
+ /* for drag & drop etc. */
+ ima = image_open_single(
+ op, filepath, bmain->name,
+ is_relative_path, use_multiview, 1);
}
- /* only image path after save, never ibuf */
- if (is_relative_path) {
- if (!exists) {
- BLI_path_rel(ima->name, bmain->name);
- }
+ if (ima == NULL) {
+ return OPERATOR_CANCELLED;
}
/* hook into UI */
@@ -1245,11 +1284,8 @@ static int image_open_exec(bContext *C, wmOperator *op)
if (iod->pprop.prop) {
/* when creating new ID blocks, use is already 1, but RNA
- * pointer se also increases user, so this compensates it */
+ * pointer also increases user, so this compensates it */
id_us_min(&ima->id);
- if ((frame_seq_len > 1) && ima->source == IMA_SRC_FILE) {
- ima->source = IMA_SRC_SEQUENCE;
- }
RNA_id_pointer_create(&ima->id, &idptr);
RNA_property_pointer_set(&iod->pprop.ptr, iod->pprop.prop, idptr);
RNA_property_update(C, &iod->pprop.ptr, iod->pprop.prop);
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 7b7ea180604..14efd4338b4 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -1234,106 +1234,106 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
UI_icon_draw(x, y, ICON_DOT); break;
}
}
- else if (GS(tselem->id->name) == ID_OB) {
- Object *ob = (Object *)tselem->id;
- switch (ob->type) {
- case OB_LAMP:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LAMP); break;
- case OB_MESH:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_MESH); break;
- case OB_CAMERA:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CAMERA); break;
- case OB_CURVE:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CURVE); break;
- case OB_MBALL:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_META); break;
- case OB_LATTICE:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LATTICE); break;
- case OB_ARMATURE:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_ARMATURE); break;
- case OB_FONT:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_FONT); break;
- case OB_SURF:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SURFACE); break;
- case OB_SPEAKER:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SPEAKER); break;
- case OB_EMPTY:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY); break;
-
+ else if (tselem->id) {
+ if (GS(tselem->id->name) == ID_OB) {
+ Object *ob = (Object *)tselem->id;
+ switch (ob->type) {
+ case OB_LAMP:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LAMP); break;
+ case OB_MESH:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_MESH); break;
+ case OB_CAMERA:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CAMERA); break;
+ case OB_CURVE:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CURVE); break;
+ case OB_MBALL:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_META); break;
+ case OB_LATTICE:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LATTICE); break;
+ case OB_ARMATURE:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_ARMATURE); break;
+ case OB_FONT:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_FONT); break;
+ case OB_SURF:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SURFACE); break;
+ case OB_SPEAKER:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SPEAKER); break;
+ case OB_EMPTY:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY); break;
+ }
}
- }
- else {
- switch (GS(tselem->id->name)) {
- case ID_SCE:
- tselem_draw_icon_uibut(&arg, ICON_SCENE_DATA); break;
- case ID_ME:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_MESH); break;
- case ID_CU:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CURVE); break;
- case ID_MB:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_META); break;
- case ID_LT:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LATTICE); break;
- case ID_LA:
- {
- Lamp *la = (Lamp *)tselem->id;
-
- switch (la->type) {
- case LA_LOCAL:
- tselem_draw_icon_uibut(&arg, ICON_LAMP_POINT); break;
- case LA_SUN:
- tselem_draw_icon_uibut(&arg, ICON_LAMP_SUN); break;
- case LA_SPOT:
- tselem_draw_icon_uibut(&arg, ICON_LAMP_SPOT); break;
- case LA_HEMI:
- tselem_draw_icon_uibut(&arg, ICON_LAMP_HEMI); break;
- case LA_AREA:
- tselem_draw_icon_uibut(&arg, ICON_LAMP_AREA); break;
- default:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LAMP); break;
+ else {
+ switch (GS(tselem->id->name)) {
+ case ID_SCE:
+ tselem_draw_icon_uibut(&arg, ICON_SCENE_DATA); break;
+ case ID_ME:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_MESH); break;
+ case ID_CU:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CURVE); break;
+ case ID_MB:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_META); break;
+ case ID_LT:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LATTICE); break;
+ case ID_LA:
+ {
+ Lamp *la = (Lamp *)tselem->id;
+ switch (la->type) {
+ case LA_LOCAL:
+ tselem_draw_icon_uibut(&arg, ICON_LAMP_POINT); break;
+ case LA_SUN:
+ tselem_draw_icon_uibut(&arg, ICON_LAMP_SUN); break;
+ case LA_SPOT:
+ tselem_draw_icon_uibut(&arg, ICON_LAMP_SPOT); break;
+ case LA_HEMI:
+ tselem_draw_icon_uibut(&arg, ICON_LAMP_HEMI); break;
+ case LA_AREA:
+ tselem_draw_icon_uibut(&arg, ICON_LAMP_AREA); break;
+ default:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LAMP); break;
+ }
+ break;
}
- break;
+ case ID_MA:
+ tselem_draw_icon_uibut(&arg, ICON_MATERIAL_DATA); break;
+ case ID_TE:
+ tselem_draw_icon_uibut(&arg, ICON_TEXTURE_DATA); break;
+ case ID_IM:
+ tselem_draw_icon_uibut(&arg, ICON_IMAGE_DATA); break;
+ case ID_SPK:
+ case ID_SO:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_SPEAKER); break;
+ case ID_AR:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_ARMATURE); break;
+ case ID_CA:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CAMERA); break;
+ case ID_KE:
+ tselem_draw_icon_uibut(&arg, ICON_SHAPEKEY_DATA); break;
+ case ID_WO:
+ tselem_draw_icon_uibut(&arg, ICON_WORLD_DATA); break;
+ case ID_AC:
+ tselem_draw_icon_uibut(&arg, ICON_ACTION); break;
+ case ID_NLA:
+ tselem_draw_icon_uibut(&arg, ICON_NLA); break;
+ case ID_TXT:
+ tselem_draw_icon_uibut(&arg, ICON_SCRIPT); break;
+ case ID_GR:
+ tselem_draw_icon_uibut(&arg, ICON_GROUP); break;
+ case ID_LI:
+ if (tselem->id->tag & LIB_TAG_MISSING) {
+ tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_BROKEN);
+ }
+ else if (((Library *)tselem->id)->parent) {
+ tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_INDIRECT);
+ }
+ else {
+ tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT);
+ }
+ break;
+ case ID_LS:
+ tselem_draw_icon_uibut(&arg, ICON_LINE_DATA); break;
+ case ID_GD:
+ tselem_draw_icon_uibut(&arg, ICON_GREASEPENCIL); break;
}
- case ID_MA:
- tselem_draw_icon_uibut(&arg, ICON_MATERIAL_DATA); break;
- case ID_TE:
- tselem_draw_icon_uibut(&arg, ICON_TEXTURE_DATA); break;
- case ID_IM:
- tselem_draw_icon_uibut(&arg, ICON_IMAGE_DATA); break;
- case ID_SPK:
- case ID_SO:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_SPEAKER); break;
- case ID_AR:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_ARMATURE); break;
- case ID_CA:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CAMERA); break;
- case ID_KE:
- tselem_draw_icon_uibut(&arg, ICON_SHAPEKEY_DATA); break;
- case ID_WO:
- tselem_draw_icon_uibut(&arg, ICON_WORLD_DATA); break;
- case ID_AC:
- tselem_draw_icon_uibut(&arg, ICON_ACTION); break;
- case ID_NLA:
- tselem_draw_icon_uibut(&arg, ICON_NLA); break;
- case ID_TXT:
- tselem_draw_icon_uibut(&arg, ICON_SCRIPT); break;
- case ID_GR:
- tselem_draw_icon_uibut(&arg, ICON_GROUP); break;
- case ID_LI:
- if (tselem->id->tag & LIB_TAG_MISSING) {
- tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_BROKEN);
- }
- else if (((Library *)tselem->id)->parent) {
- tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_INDIRECT);
- }
- else {
- tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT);
- }
- break;
- case ID_LS:
- tselem_draw_icon_uibut(&arg, ICON_LINE_DATA); break;
- case ID_GD:
- tselem_draw_icon_uibut(&arg, ICON_GREASEPENCIL); break;
}
}
}
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index f3235d07757..111e60e5159 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -439,7 +439,7 @@ static void id_local_cb(
Main *bmain = CTX_data_main(C);
/* if the ID type has no special local function,
* just clear the lib */
- if (id_make_local(bmain, tselem->id, false) == false) {
+ if (id_make_local(bmain, tselem->id, false, false) == false) {
id_clear_lib_data(bmain, tselem->id);
}
}
@@ -516,23 +516,16 @@ static void group_linkobs2scene_cb(
Group *group = (Group *)tselem->id;
GroupObject *gob;
Base *base;
-
+
for (gob = group->gobject.first; gob; gob = gob->next) {
base = BKE_scene_base_find(scene, gob->ob);
- if (base) {
- base->object->flag |= SELECT;
- base->flag |= SELECT;
- }
- else {
+ if (!base) {
/* link to scene */
- base = MEM_callocN(sizeof(Base), "add_base");
- BLI_addhead(&scene->base, base);
- base->lay = gob->ob->lay;
- gob->ob->flag |= SELECT;
- base->flag = gob->ob->flag;
- base->object = gob->ob;
+ base = BKE_scene_base_add(scene, gob->ob);
id_lib_extern((ID *)gob->ob); /* in case these are from a linked group */
}
+ base->object->flag |= SELECT;
+ base->flag |= SELECT;
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index c11a4d2e5a3..ede6b7ce469 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -1071,7 +1071,7 @@ static int sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, const
{
bool is_type_set = RNA_struct_property_is_set(op->ptr, "type");
int type = -1;
- int prop_flag = SEQPROP_ENDFRAME;
+ int prop_flag = SEQPROP_ENDFRAME | SEQPROP_NOPATHS;
if (is_type_set) {
type = RNA_enum_get(op->ptr, "type");
@@ -1106,9 +1106,6 @@ void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_filesel(
- ot, 0, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME);
RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_TYPE_CROSS, "Type", "Sequencer effect type");
RNA_def_float_vector(ot->srna, "color", 3, NULL, 0.0f, 1.0f, "Color",
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 2b0bd7690e2..83fde34fcde 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -3075,7 +3075,9 @@ static int viewselected_exec(bContext *C, wmOperator *op)
else if (BKE_paint_select_face_test(ob)) {
ok = paintface_minmax(ob, min, max);
}
- else if (ob && (ob->mode & (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT))) {
+ else if (ob &&
+ (ob->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)))
+ {
BKE_paint_stroke_get_average(scene, ob, min);
copy_v3_v3(max, min);
ok = true;
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 2d050c4fa95..c5026fbb32b 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -274,6 +274,7 @@ bool ED_view3d_minmax_verts(struct Object *obedit, float min[3], float max[3]);
void VIEW3D_OT_snap_selected_to_grid(struct wmOperatorType *ot);
void VIEW3D_OT_snap_selected_to_cursor(struct wmOperatorType *ot);
+void VIEW3D_OT_snap_selected_to_active(struct wmOperatorType *ot);
void VIEW3D_OT_snap_cursor_to_grid(struct wmOperatorType *ot);
void VIEW3D_OT_snap_cursor_to_center(struct wmOperatorType *ot);
void VIEW3D_OT_snap_cursor_to_selected(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 1c84ce3c985..b273f46fca3 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -214,6 +214,7 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_snap_selected_to_grid);
WM_operatortype_append(VIEW3D_OT_snap_selected_to_cursor);
+ WM_operatortype_append(VIEW3D_OT_snap_selected_to_active);
WM_operatortype_append(VIEW3D_OT_snap_cursor_to_grid);
WM_operatortype_append(VIEW3D_OT_snap_cursor_to_center);
WM_operatortype_append(VIEW3D_OT_snap_cursor_to_selected);
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index ac05853e6d0..7448d4c658e 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -312,25 +312,9 @@ static void view3d_win_to_ray_segment(
if (!r_ray_co) r_ray_co = _ray_co;
if (!r_ray_dir) r_ray_dir = _ray_dir;
+ ED_view3d_win_to_origin(ar, mval, r_ray_co);
ED_view3d_win_to_vector(ar, mval, r_ray_dir);
- if (rv3d->is_persp) {
- copy_v3_v3(r_ray_co, rv3d->viewinv[3]);
- }
- else {
- r_ray_co[0] = 2.0f * mval[0] / ar->winx - 1.0f;
- r_ray_co[1] = 2.0f * mval[1] / ar->winy - 1.0f;
-
- if (rv3d->persp == RV3D_CAMOB) {
- r_ray_co[2] = -1.0f;
- }
- else {
- r_ray_co[2] = 0.0f;
- }
-
- mul_project_m4_v3(rv3d->persinv, r_ray_co);
- }
-
if ((rv3d->is_persp == false) && (rv3d->persp != RV3D_CAMOB)) {
end_offset = v3d->far / 2.0f;
start_offset = -end_offset;
@@ -347,7 +331,7 @@ static void view3d_win_to_ray_segment(
}
}
-BLI_INLINE bool view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float ray_end[3])
+bool ED_view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float ray_end[3])
{
if ((rv3d->rflag & RV3D_CLIPPING) &&
(clip_segment_v3_plane_n(ray_start, ray_end, rv3d->clip, 6,
@@ -384,7 +368,7 @@ bool ED_view3d_win_to_ray_ex(
/* bounds clipping */
if (do_clip) {
- return view3d_clip_segment(ar->regiondata, r_ray_start, ray_end);
+ return ED_view3d_clip_segment(ar->regiondata, r_ray_start, ray_end);
}
return true;
@@ -549,6 +533,37 @@ void ED_view3d_win_to_delta(const ARegion *ar, const float mval[2], float out[3]
}
/**
+ * Calculate a 3d origin from 2d window coordinates.
+ * \note Orthographic views have a less obvious origin,
+ * Since far clip can be a very large value resulting in numeric precision issues,
+ * the origin in this case is close to zero coordinate.
+ *
+ * \param ar The region (used for the window width and height).
+ * \param mval The area relative 2d location (such as event->mval converted to floats).
+ * \param out The resulting normalized world-space direction vector.
+ */
+void ED_view3d_win_to_origin(const ARegion *ar, const float mval[2], float out[3])
+{
+ RegionView3D *rv3d = ar->regiondata;
+ if (rv3d->is_persp) {
+ copy_v3_v3(out, rv3d->viewinv[3]);
+ }
+ else {
+ out[0] = 2.0f * mval[0] / ar->winx - 1.0f;
+ out[1] = 2.0f * mval[1] / ar->winy - 1.0f;
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ out[2] = -1.0f;
+ }
+ else {
+ out[2] = 0.0f;
+ }
+
+ mul_project_m4_v3(rv3d->persinv, out);
+ }
+}
+
+/**
* Calculate a 3d direction vector from 2d window coordinates.
* This direction vector starts and the view in the direction of the 2d window coordinates.
* In orthographic view all window coordinates yield the same vector.
@@ -599,7 +614,7 @@ bool ED_view3d_win_to_segment(const ARegion *ar, View3D *v3d, const float mval[2
/* bounds clipping */
if (do_clip) {
- return view3d_clip_segment((RegionView3D *)ar->regiondata, r_ray_start, r_ray_end);
+ return ED_view3d_clip_segment((RegionView3D *)ar->regiondata, r_ray_start, r_ray_end);
}
return true;
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index e8e7d3c62fb..5dd69cc66eb 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -44,6 +44,7 @@
#include "BKE_main.h"
#include "BKE_mball.h"
#include "BKE_object.h"
+#include "BKE_report.h"
#include "BKE_tracking.h"
#include "WM_api.h"
@@ -204,7 +205,7 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
/* *************************************************** */
-static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
+static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset)
{
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
@@ -213,15 +214,10 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
TransVertStore tvs = {NULL};
TransVert *tv;
float imat[3][3], bmat[3][3];
- const float *cursor_global;
float center_global[3];
float offset_global[3];
int a;
- const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
-
- cursor_global = ED_view3d_cursor3d_get(scene, v3d);
-
if (use_offset) {
if ((v3d && v3d->around == V3D_AROUND_ACTIVE) &&
snap_calc_active_center(C, true, center_global))
@@ -231,11 +227,11 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
else {
snap_curs_to_sel_ex(C, center_global);
}
- sub_v3_v3v3(offset_global, cursor_global, center_global);
+ sub_v3_v3v3(offset_global, snap_target_global, center_global);
}
if (obedit) {
- float cursor_local[3];
+ float snap_target_local[3];
if (ED_transverts_check_obedit(obedit))
ED_transverts_create_from_obedit(&tvs, obedit, 0);
@@ -246,8 +242,8 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
invert_m3_m3(imat, bmat);
/* get the cursor in object space */
- sub_v3_v3v3(cursor_local, cursor_global, obedit->obmat[3]);
- mul_m3_v3(imat, cursor_local);
+ sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]);
+ mul_m3_v3(imat, snap_target_local);
if (use_offset) {
float offset_local[3];
@@ -262,7 +258,7 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
else {
tv = tvs.transverts;
for (a = 0; a < tvs.transverts_tot; a++, tv++) {
- copy_v3_v3(tv->loc, cursor_local);
+ copy_v3_v3(tv->loc, snap_target_local);
}
}
@@ -274,10 +270,10 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
bPoseChannel *pchan;
bArmature *arm = obact->data;
- float cursor_local[3];
+ float snap_target_local[3];
invert_m4_m4(obact->imat, obact->obmat);
- mul_v3_m4v3(cursor_local, obact->imat, cursor_global);
+ mul_v3_m4v3(snap_target_local, obact->imat, snap_target_global);
for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
if ((pchan->bone->flag & BONE_SELECTED) &&
@@ -311,7 +307,7 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose);
}
else {
- BKE_armature_loc_pose_to_bone(pchan, cursor_local, cursor_pose);
+ BKE_armature_loc_pose_to_bone(pchan, snap_target_local, cursor_pose);
}
/* copy new position */
@@ -367,7 +363,7 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global);
}
else {
- copy_v3_v3(cursor_parent, cursor_global);
+ copy_v3_v3(cursor_parent, snap_target_global);
}
sub_v3_v3(cursor_parent, ob->obmat[3]);
@@ -401,6 +397,18 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static int snap_selected_to_cursor_exec(bContext *C, wmOperator *op)
+{
+ const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
+
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ const float *snap_target_global = ED_view3d_cursor3d_get(scene, v3d);
+
+ return snap_selected_to_location(C, snap_target_global, use_offset);
+}
+
void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
{
/* identifiers */
@@ -409,7 +417,7 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
ot->idname = "VIEW3D_OT_snap_selected_to_cursor";
/* api callbacks */
- ot->exec = snap_sel_to_curs_exec;
+ ot->exec = snap_selected_to_cursor_exec;
ot->poll = ED_operator_view3d_active;
/* flags */
@@ -419,6 +427,34 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_offset", 1, "Offset", "");
}
+static int snap_selected_to_active_exec(bContext *C, wmOperator *op)
+{
+ float snap_target_global[3];
+
+ if (snap_calc_active_center(C, false, snap_target_global) == false) {
+ BKE_report(op->reports, RPT_ERROR, "No active element found!");
+ return OPERATOR_CANCELLED;
+ }
+
+ return snap_selected_to_location(C, snap_target_global, false);
+}
+
+void VIEW3D_OT_snap_selected_to_active(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Snap Selection to Active";
+ ot->description = "Snap selected item(s) to the active item";
+ ot->idname = "VIEW3D_OT_snap_selected_to_active";
+
+ /* api callbacks */
+ ot->exec = snap_selected_to_active_exec;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
/* *************************************************** */
static int snap_curs_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index ed6d49da681..724eba160a0 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -110,6 +110,12 @@ struct SnapObjectContext {
};
+enum eViewProj {
+ VIEW_PROJ_NONE = -1,
+ VIEW_PROJ_ORTHO = 0,
+ VIEW_PROJ_PERSP = -1,
+};
+
static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt);
@@ -137,10 +143,6 @@ struct RayCastAll_Data {
Object *ob;
unsigned int ob_uuid;
- /* DerivedMesh only */
- DerivedMesh *dm;
- const struct MLoopTri *dm_looptri;
-
/* output data */
ListBase *hit_list;
bool retval;
@@ -218,76 +220,177 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH
/* -------------------------------------------------------------------- */
-/** \name Internal Object Snapping API
+/** \Common utilities
* \{ */
+
+/**
+ * Struct that kepts basic information about a BVHTree build from a editmesh.
+ */
+typedef struct BVHTreeFromMeshType {
+ void *userdata;
+ char type;
+} BVHTreeFromMeshType;
+
+typedef struct PreDefProject {
+ float pmat[4][4]; /* perspective matrix multiplied by object matrix */
+ float win_half[2];
+ float dist_px_sq;
+} PreDefProject;
+
+static void precalc_project(
+ PreDefProject *projectdefs, const ARegion *ar,
+ const float dist_px, float obmat[4][4])
+{
+ float (*pmat)[4] = ((RegionView3D *)ar->regiondata)->persmat;
+ if (obmat) {
+ mul_m4_m4m4(projectdefs->pmat, pmat, obmat);
+ }
+ else {
+ copy_m4_m4(projectdefs->pmat, pmat);
+ }
+ projectdefs->win_half[0] = ar->winx / 2;
+ projectdefs->win_half[1] = ar->winy / 2;
+ projectdefs->dist_px_sq = SQUARE(dist_px);
+}
+
+/**
+ * From a threshold (maximum distance to snap in pixels) returns:
+ *
+ * - The *real* distance (3D) if you are in orthographic-view.
+ * - The *tangent* (view cone radius at distance 1.0) if you are in perspective-view.
+ */
+static float dist_px_to_dist3d_or_tangent(const ARegion *ar, const float dist_px)
+{
+ const RegionView3D *rv3d = ar->regiondata;
+ if (ar->winx >= ar->winy)
+ return 2 * (dist_px / ar->winx) / rv3d->winmat[0][0];
+ else
+ return 2 * (dist_px / ar->winy) / rv3d->winmat[1][1];
+}
+
+static const float *get_vert_co(const BVHTreeFromMeshType *meshdata, const int index)
+{
+ switch (meshdata->type) {
+ case SNAP_MESH:
+ {
+ BVHTreeFromMesh *data = meshdata->userdata;
+ const MVert *vert = data->vert;
+ return vert[index].co;
+ }
+ case SNAP_EDIT_MESH:
+ {
+ BVHTreeFromEditMesh *data = meshdata->userdata;
+ BMVert *eve = BM_vert_at_index(data->em->bm, index);
+ return eve->co;
+ }
+ }
+ return NULL;
+}
+
+static void copy_vert_no(const BVHTreeFromMeshType *meshdata, const int index, float r_no[3])
+{
+ switch (meshdata->type) {
+ case SNAP_MESH:
+ {
+ BVHTreeFromMesh *data = meshdata->userdata;
+ const MVert *vert = data->vert;
+ normal_short_to_float_v3(r_no, vert->no);
+ break;
+ }
+ case SNAP_EDIT_MESH:
+ {
+ BVHTreeFromEditMesh *data = meshdata->userdata;
+ BMVert *eve = BM_vert_at_index(data->em->bm, index);
+ copy_v3_v3(r_no, eve->no);
+ break;
+ }
+ }
+}
+
+static void get_edge_verts(
+ const BVHTreeFromMeshType *meshdata, const int index,
+ const float *v_pair[2])
+{
+ switch (meshdata->type) {
+ case SNAP_MESH:
+ {
+ BVHTreeFromMesh *data = meshdata->userdata;
+
+ const MVert *vert = data->vert;
+ const MEdge *edge = data->edge + index;
+
+ v_pair[0] = vert[edge->v1].co;
+ v_pair[1] = vert[edge->v2].co;
+ break;
+ }
+ case SNAP_EDIT_MESH:
+ {
+ BVHTreeFromEditMesh *data = meshdata->userdata;
+ BMEdge *eed = BM_edge_at_index(data->em->bm, index);
+
+ v_pair[0] = eed->v1->co;
+ v_pair[1] = eed->v2->co;
+ break;
+ }
+ }
+}
+
#define V3_MUL_ELEM(a, b) \
(a)[0] * (b)[0], \
(a)[1] * (b)[1], \
(a)[2] * (b)[2]
-static bool test_vert(
- const float vco[3], const float vno[3], const float ray_co[3], const float ray_dir[3],
- const float ray_depth_range[2], const float scale[3], const bool is_persp,
+static bool test_vert_dist(
+ const float vco[3], const float ray_co[3], const float ray_dir[3],
+ const float ray_depth_range[2], const float scale[3],
/* read/write args */
float *ray_depth, float *dist_to_ray_sq,
/* return args */
- float r_co[3], float r_no[3])
+ float r_co[3])
{
const float vco_sc[3] = {V3_MUL_ELEM(vco, scale)};
- const float co_sc[3] = {V3_MUL_ELEM(ray_co, scale)};
+ const float origin_sc[3] = {V3_MUL_ELEM(ray_co, scale)};
const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)};
- float depth;
- float dist_sq = dist_squared_to_ray_v3(co_sc, dir_sc, vco_sc, &depth);
+ float depth, dist_sq;
+ dist_sq = dist_squared_to_ray_v3(origin_sc, dir_sc, vco_sc, &depth);
if (depth < ray_depth_range[0]) {
return false;
}
- if (is_persp) {
- dist_sq /= SQUARE(depth);
- }
-
if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) {
*dist_to_ray_sq = dist_sq;
copy_v3_v3(r_co, vco);
- if (vno) {
- copy_v3_v3(r_no, vno);
- }
-
*ray_depth = depth;
return true;
}
return false;
}
-static bool test_edge(
+static bool test_edge_dist(
const float v1[3], const float v2[3], const float ray_co[3], const float ray_dir[3],
- const float ray_depth_range[2], const float scale[3], const bool is_persp,
+ const float ray_depth_range[2], const float scale[3],
/* read/write args */
float *ray_depth, float *dist_to_ray_sq,
/* return args */
- float r_co[3], float r_no[3])
+ float r_co[3])
{
const float v1_sc[3] = {V3_MUL_ELEM(v1, scale)};
const float v2_sc[3] = {V3_MUL_ELEM(v2, scale)};
const float co_sc[3] = {V3_MUL_ELEM(ray_co, scale)};
const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)};
- float tmp_co[3], depth;
- float dist_sq = dist_squared_ray_to_seg_v3(co_sc, dir_sc, v1_sc, v2_sc, tmp_co, &depth);
+ float tmp_co[3], depth, dist_sq;
+ dist_sq = dist_squared_ray_to_seg_v3(co_sc, dir_sc, v1_sc, v2_sc, tmp_co, &depth);
if (depth < ray_depth_range[0]) {
return false;
}
- if (is_persp) {
- dist_sq /= SQUARE(depth);
- }
-
if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) {
*dist_to_ray_sq = dist_sq;
@@ -297,10 +400,6 @@ static bool test_edge(
copy_v3_v3(r_co, tmp_co);
- if (r_no) {
- sub_v3_v3v3(r_no, v1, v2);
- }
-
*ray_depth = depth;
return true;
}
@@ -309,50 +408,369 @@ static bool test_edge(
#undef V3_MUL_ELEM
+static bool test_projected_vert_dist(
+ PreDefProject *projectdefs,
+ const float co[3], const enum eViewProj view_proj,
+ const float mval[2], const float depth_range[2],
+ float r_co[3])
+{
+ float depth;
+ float(*pmat)[4] = projectdefs->pmat;
+ if (view_proj == VIEW_PROJ_PERSP) {
+ depth = mul_project_m4_v3_zfac(pmat, co);
+ if (depth < depth_range[0] || depth > depth_range[1]) {
+ return false;
+ }
+ }
+
+ float co2d[2] = {
+ (dot_m4_v3_row_x(pmat, co) + pmat[3][0]),
+ (dot_m4_v3_row_y(pmat, co) + pmat[3][1]),
+ };
+
+ if (view_proj == VIEW_PROJ_PERSP) {
+ mul_v2_fl(co2d, 1 / depth);
+ }
+
+ co2d[0] += 1.0f;
+ co2d[1] += 1.0f;
+ co2d[0] *= projectdefs->win_half[0];
+ co2d[1] *= projectdefs->win_half[1];
+
+ const float dist_sq = len_squared_v2v2(mval, co2d);
+ if (dist_sq < projectdefs->dist_px_sq) {
+ copy_v3_v3(r_co, co);
+ projectdefs->dist_px_sq = dist_sq;
+ return true;
+ }
+ return false;
+}
+
+static bool test_projected_edge_dist(
+ PreDefProject *projectdefs,
+ const float va[3], const float vb[3], const float ray_start[3], const float ray_normal[3],
+ const enum eViewProj view_proj, const float mval[2], const float depth_range[2],
+ float r_co[3])
+{
+
+ float tmp_co[3], depth;
+ dist_squared_ray_to_seg_v3(ray_start, ray_normal, va, vb, tmp_co, &depth);
+ return test_projected_vert_dist(projectdefs, tmp_co, view_proj, mval, depth_range, r_co);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \Walk DFS
+ * \{ */
+typedef struct Object_Nearest2dPrecalc {
+ float ray_origin_local[3];
+ float ray_direction_local[3];
+ float ray_inv_dir[3];
+
+ PreDefProject projectdefs;
+ float mval[2];
+ bool sign[3];
+ bool r_axis_closest[3];
+ float depth_range[2];
+
+ void *userdata;
+ int index;
+ float co[3];
+ float no[3];
+} Object_Nearest2dPrecalc;
+
+
+static void nearest2d_precalc(
+ Object_Nearest2dPrecalc *neasrest_precalc, const ARegion *ar,
+ const float dist_px, float obmat[4][4],
+ const float ray_origin_local[3], const float ray_direction_local[3],
+ const float mval[2], const float depth_range[2])
+{
+ precalc_project(&neasrest_precalc->projectdefs, ar, dist_px, obmat);
+ copy_v3_v3(neasrest_precalc->ray_origin_local, ray_origin_local);
+ copy_v3_v3(neasrest_precalc->ray_direction_local, ray_direction_local);
+ copy_v2_v2(neasrest_precalc->mval, mval);
+ copy_v2_v2(neasrest_precalc->depth_range, depth_range);
+
+ for (int i = 0; i < 3; i++) {
+ neasrest_precalc->ray_inv_dir[i] =
+ (neasrest_precalc->ray_direction_local[i] != 0.0f) ?
+ (1.0f / neasrest_precalc->ray_direction_local[i]) : FLT_MAX;
+ neasrest_precalc->sign[i] = (neasrest_precalc->ray_inv_dir[i] < 0.0f);
+ neasrest_precalc->r_axis_closest[i] = true;
+ }
+}
+
+static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *user_data)
+{
+ Object_Nearest2dPrecalc *data = user_data;
+ float local_bvmin[3], local_bvmax[3];
+ if (data->sign[0]) {
+ local_bvmin[0] = bounds[0].max;
+ local_bvmax[0] = bounds[0].min;
+ }
+ else {
+ local_bvmin[0] = bounds[0].min;
+ local_bvmax[0] = bounds[0].max;
+ }
+ if (data->sign[1]) {
+ local_bvmin[1] = bounds[1].max;
+ local_bvmax[1] = bounds[1].min;
+ }
+ else {
+ local_bvmin[1] = bounds[1].min;
+ local_bvmax[1] = bounds[1].max;
+ }
+ if (data->sign[2]) {
+ local_bvmin[2] = bounds[2].max;
+ local_bvmax[2] = bounds[2].min;
+ }
+ else {
+ local_bvmin[2] = bounds[2].min;
+ local_bvmax[2] = bounds[2].max;
+ }
+
+ const float tmin[3] = {
+ (local_bvmin[0] - data->ray_origin_local[0]) * data->ray_inv_dir[0],
+ (local_bvmin[1] - data->ray_origin_local[1]) * data->ray_inv_dir[1],
+ (local_bvmin[2] - data->ray_origin_local[2]) * data->ray_inv_dir[2],
+ };
+ const float tmax[3] = {
+ (local_bvmax[0] - data->ray_origin_local[0]) * data->ray_inv_dir[0],
+ (local_bvmax[1] - data->ray_origin_local[1]) * data->ray_inv_dir[1],
+ (local_bvmax[2] - data->ray_origin_local[2]) * data->ray_inv_dir[2],
+ };
+ float va[3], vb[3];
+ float rtmin, rtmax;
+ int main_axis;
+
+ if ((tmax[0] <= tmax[1]) && (tmax[0] <= tmax[2])) {
+ rtmax = tmax[0];
+ va[0] = vb[0] = local_bvmax[0];
+ main_axis = 3;
+ data->r_axis_closest[0] = data->sign[0];
+ }
+ else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) {
+ rtmax = tmax[1];
+ va[1] = vb[1] = local_bvmax[1];
+ main_axis = 2;
+ data->r_axis_closest[1] = data->sign[1];
+ }
+ else {
+ rtmax = tmax[2];
+ va[2] = vb[2] = local_bvmax[2];
+ main_axis = 1;
+ data->r_axis_closest[2] = data->sign[2];
+ }
+
+ if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) {
+ rtmin = tmin[0];
+ va[0] = vb[0] = local_bvmin[0];
+ main_axis -= 3;
+ data->r_axis_closest[0] = !data->sign[0];
+ }
+ else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) {
+ rtmin = tmin[1];
+ va[1] = vb[1] = local_bvmin[1];
+ main_axis -= 1;
+ data->r_axis_closest[1] = !data->sign[1];
+ }
+ else {
+ rtmin = tmin[2];
+ va[2] = vb[2] = local_bvmin[2];
+ main_axis -= 2;
+ data->r_axis_closest[2] = !data->sign[2];
+ }
+ if (main_axis < 0) {
+ main_axis += 3;
+ }
+
+ /* if rtmin < rtmax, ray intersect `AABB` */
+ if (rtmin <= rtmax) {
+#ifdef IGNORE_BEHIND_RAY
+ /* `if rtmax < depth_min`, the whole `AABB` is behind us */
+ if (rtmax < min_depth) {
+ return fallback;
+ }
+#endif
+ const float proj = rtmin * data->ray_direction_local[main_axis];
+ data->r_axis_closest[main_axis] = (proj - va[main_axis]) < (vb[main_axis] - proj);
+ return true;
+ }
+#ifdef IGNORE_BEHIND_RAY
+ /* `if rtmin < depth_min`, the whole `AABB` is behing us */
+ else if (rtmin < min_depth) {
+ return fallback;
+ }
+#endif
+ if (data->sign[main_axis]) {
+ va[main_axis] = local_bvmax[main_axis];
+ vb[main_axis] = local_bvmin[main_axis];
+ }
+ else {
+ va[main_axis] = local_bvmin[main_axis];
+ vb[main_axis] = local_bvmax[main_axis];
+ }
+ float scale = fabsf(local_bvmax[main_axis] - local_bvmin[main_axis]);
+
+ float (*pmat)[4] = data->projectdefs.pmat;
+ float depth_a = mul_project_m4_v3_zfac(pmat, va);
+ float depth_b = depth_a + pmat[main_axis][3] * scale;
+
+ float va2d[2] = {
+ (dot_m4_v3_row_x(pmat, va) + pmat[3][0]),
+ (dot_m4_v3_row_y(pmat, va) + pmat[3][1]),
+ };
+ float vb2d[2] = {
+ (va2d[0] + pmat[main_axis][0] * scale) / depth_b,
+ (va2d[1] + pmat[main_axis][1] * scale) / depth_b,
+ };
+
+ va2d[0] /= depth_a;
+ va2d[1] /= depth_a;
+
+ va2d[0] += 1.0f;
+ va2d[1] += 1.0f;
+ vb2d[0] += 1.0f;
+ vb2d[1] += 1.0f;
+
+ va2d[0] *= data->projectdefs.win_half[0];
+ va2d[1] *= data->projectdefs.win_half[1];
+ vb2d[0] *= data->projectdefs.win_half[0];
+ vb2d[1] *= data->projectdefs.win_half[1];
+
+ //float dvec[2], edge[2], rdist;
+ //sub_v2_v2v2(dvec, data->mval, va2d);
+ //sub_v2_v2v2(edge, vb2d, va2d);
+ float rdist;
+ short dvec[2] = {data->mval[0] - va2d[0], data->mval[1] - va2d[1]};
+ short edge[2] = {vb2d[0] - va2d[0], vb2d[1] - va2d[1]};
+ float lambda = dvec[0] * edge[0] + dvec[1] * edge[1];
+ if (lambda != 0.0f) {
+ lambda /= edge[0] * edge[0] + edge[1] * edge[1];
+ if (lambda <= 0.0f) {
+ rdist = len_squared_v2v2(data->mval, va2d);
+ data->r_axis_closest[main_axis] = true;
+ }
+ else if (lambda >= 1.0f) {
+ rdist = len_squared_v2v2(data->mval, vb2d);
+ data->r_axis_closest[main_axis] = false;
+ }
+ else {
+ va2d[0] += edge[0] * lambda;
+ va2d[1] += edge[1] * lambda;
+ rdist = len_squared_v2v2(data->mval, va2d);
+ data->r_axis_closest[main_axis] = lambda < 0.5f;
+ }
+ }
+ else {
+ rdist = len_squared_v2v2(data->mval, va2d);
+ }
+ return rdist < data->projectdefs.dist_px_sq;
+}
+
+static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, void *userdata)
+{
+ struct Object_Nearest2dPrecalc *neasrest_precalc = userdata;
+ const float co[3] = {
+ (bounds[0].min + bounds[0].max) / 2,
+ (bounds[1].min + bounds[1].max) / 2,
+ (bounds[2].min + bounds[2].max) / 2,
+ };
+
+ /* Currently the `BLI_bvhtree_walk_dfs` is being used only in the perspective view mode (VIEW_PROJ_PERSP)
+ * It could be used in orthographic view mode too (VIEW_PROJ_ORTHO),
+ * but in this case the `BLI_bvhtree_find_nearest_to_ray` is more efficient.*/
+ if (test_projected_vert_dist(
+ &neasrest_precalc->projectdefs, co, VIEW_PROJ_PERSP,
+ neasrest_precalc->mval, neasrest_precalc->depth_range,
+ neasrest_precalc->co))
+ {
+ copy_vert_no(neasrest_precalc->userdata, index, neasrest_precalc->no);
+ neasrest_precalc->index = index;
+ }
+ return true;
+}
+
+static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata)
+{
+ struct Object_Nearest2dPrecalc *neasrest_precalc = userdata;
+
+ const float *v_pair[2];
+ get_edge_verts(neasrest_precalc->userdata, index, v_pair);
+
+ /* Currently the `BLI_bvhtree_walk_dfs` is being used only in the perspective view mode (VIEW_PROJ_PERSP)
+ * It could be used in orthographic view mode too (VIEW_PROJ_ORTHO),
+ * but in this case the `BLI_bvhtree_find_nearest_to_ray` is more efficient.*/
+ if (test_projected_edge_dist(
+ &neasrest_precalc->projectdefs, v_pair[0], v_pair[1],
+ neasrest_precalc->ray_origin_local, neasrest_precalc->ray_direction_local,
+ VIEW_PROJ_PERSP, neasrest_precalc->mval, neasrest_precalc->depth_range,
+ neasrest_precalc->co))
+ {
+ sub_v3_v3v3(neasrest_precalc->no, v_pair[0], v_pair[1]);
+ neasrest_precalc->index = index;
+ }
+ return true;
+}
+
+static bool cb_nearest_walk_order(const BVHTreeAxisRange *UNUSED(bounds), char axis, void *userdata)
+{
+ const bool *r_axis_closest = ((struct Object_Nearest2dPrecalc *)userdata)->r_axis_closest;
+ return r_axis_closest[axis];
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Internal Object Snapping API
+ * \{ */
+
static bool snapArmature(
- Object *ob, bArmature *arm, float obmat[4][4],
- const short snap_to, const bool is_persp,
- const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2],
+ const ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4],
+ const short snap_to, const float origin[3], const float dir[3],
+ const float mval[2], const enum eViewProj view_proj, const float depth_range[2],
/* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
+ float *dist_px,
/* return args */
float r_loc[3], float *UNUSED(r_no))
{
- float imat[4][4];
- float ray_origin_local[3], ray_normal_local[3];
bool retval = false;
- invert_m4_m4(imat, obmat);
+ float ray_start_local[3], ray_normal_local[3];
+ if (snap_to != SCE_SNAP_MODE_VERTEX) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
- mul_v3_m4v3(ray_origin_local, imat, ray_origin);
- mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
+ copy_v3_v3(ray_start_local, origin);
+ copy_v3_v3(ray_normal_local, dir);
+ mul_m4_v3(imat, ray_start_local);
+ mul_mat3_m4_v3(imat, ray_normal_local);
+ }
- float ob_scale[3];
- mat4_to_size(ob_scale, obmat);
+ PreDefProject projectdefs;
+ precalc_project(&projectdefs, ar, *dist_px, obmat);
if (arm->edbo) {
- EditBone *eBone;
-
- for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
+ for (EditBone *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 |= test_vert(
- eBone->head, NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
- retval |= test_vert(
- eBone->tail, NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_vert_dist(
+ &projectdefs, eBone->head, view_proj, mval, depth_range, r_loc);
+ retval |= test_projected_vert_dist(
+ &projectdefs, eBone->tail, view_proj, mval, depth_range, r_loc);
break;
case SCE_SNAP_MODE_EDGE:
- retval |= test_edge(
- eBone->head, eBone->tail, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_edge_dist(
+ &projectdefs, eBone->head, eBone->tail, ray_start_local, ray_normal_local,
+ view_proj, mval, depth_range, r_loc);
break;
}
}
@@ -360,11 +778,8 @@ static bool snapArmature(
}
}
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;
+ for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ Bone *bone = pchan->bone;
/* skip hidden bones */
if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
const float *head_vec = pchan->pose_head;
@@ -372,26 +787,22 @@ static bool snapArmature(
switch (snap_to) {
case SCE_SNAP_MODE_VERTEX:
- retval |= test_vert(
- head_vec, NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
- retval |= test_vert(
- tail_vec, NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_vert_dist(
+ &projectdefs, head_vec, view_proj, mval, depth_range, r_loc);
+ retval |= test_projected_vert_dist(
+ &projectdefs, tail_vec, view_proj, mval, depth_range, r_loc);
break;
case SCE_SNAP_MODE_EDGE:
- retval |= test_edge(
- head_vec, tail_vec, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_edge_dist(
+ &projectdefs, head_vec, tail_vec, ray_start_local, ray_normal_local,
+ view_proj, mval, depth_range, r_loc);
break;
}
}
}
}
if (retval) {
+ *dist_px = sqrtf(projectdefs.dist_px_sq);
mul_m4_v3(obmat, r_loc);
return true;
}
@@ -399,39 +810,26 @@ static bool snapArmature(
}
static bool snapCurve(
- Object *ob, Curve *cu, float obmat[4][4],
- const short snap_to, const bool is_persp,
- const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2],
+ const ARegion *ar, Object *ob, Curve *cu, float obmat[4][4],
+ const short snap_to, const float mval[2], const enum eViewProj view_proj,
+ const float depth_range[2],
/* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
+ float *dist_px,
/* return args */
float r_loc[3], float *UNUSED(r_no))
{
- float imat[4][4];
- float ray_origin_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_origin_local, ray_origin);
- copy_v3_v3(ray_normal_local, ray_normal);
-
- mul_m4_v3(imat, ray_origin_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
-
- float ob_scale[3];
- mat4_to_size(ob_scale, obmat);
+ PreDefProject projectdefs;
+ precalc_project(&projectdefs, ar, *dist_px, obmat);
- 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++) {
+ for (Nurb *nu = (ob->mode == OB_MODE_EDIT ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
+ for (int u = 0; u < nu->pntsu; u++) {
switch (snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
@@ -441,26 +839,20 @@ static bool snapCurve(
if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) {
break;
}
- retval |= test_vert(
- nu->bezt[u].vec[1], NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_vert_dist(
+ &projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc);
/* 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 |= test_vert(
- nu->bezt[u].vec[0], NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_vert_dist(
+ &projectdefs, nu->bezt[u].vec[0], view_proj, mval, depth_range, r_loc);
}
if (!(nu->bezt[u].f3 & SELECT) &&
!(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT))
{
- retval |= test_vert(
- nu->bezt[u].vec[2], NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_vert_dist(
+ &projectdefs, nu->bezt[u].vec[2], view_proj, mval, depth_range, r_loc);
}
}
else {
@@ -468,26 +860,20 @@ static bool snapCurve(
if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) {
break;
}
- retval |= test_vert(
- nu->bp[u].vec, NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_vert_dist(
+ &projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc);
}
}
else {
/* curve is not visible outside editmode if nurb length less than two */
if (nu->pntsu > 1) {
if (nu->bezt) {
- retval |= test_vert(
- nu->bezt[u].vec[1], NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_vert_dist(
+ &projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc);
}
else {
- retval |= test_vert(
- nu->bp[u].vec, NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_vert_dist(
+ &projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc);
}
}
}
@@ -499,6 +885,7 @@ static bool snapCurve(
}
}
if (retval) {
+ *dist_px = sqrtf(projectdefs.dist_px_sq);
mul_m4_v3(obmat, r_loc);
return true;
}
@@ -507,11 +894,11 @@ static bool snapCurve(
/* may extend later (for now just snaps to empty center) */
static bool snapEmpty(
- Object *ob, float obmat[4][4],
- const short snap_to, const bool is_persp,
- const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2],
+ const ARegion *ar, Object *ob, float obmat[4][4],
+ const short snap_to, const float mval[2], const enum eViewProj view_proj,
+ const float depth_range[2],
/* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
+ float *dist_px,
/* return args */
float r_loc[3], float *UNUSED(r_no))
{
@@ -520,17 +907,19 @@ static bool snapEmpty(
if (ob->transflag & OB_DUPLI) {
return retval;
}
+
/* for now only vertex supported */
switch (snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
- float ob_loc[3], ob_scale[3] = {1.0, 1.0, 1.0};
- copy_v3_v3(ob_loc, obmat[3]);
-
- retval |= test_vert(
- ob_loc, NULL, ray_origin, ray_normal,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ PreDefProject projectdefs;
+ precalc_project(&projectdefs, ar, *dist_px, NULL);
+ float tmp_co[3];
+ copy_v3_v3(tmp_co, obmat[3]);
+ if (test_projected_vert_dist(&projectdefs, tmp_co, view_proj, mval, depth_range, r_loc)) {
+ *dist_px = sqrtf(projectdefs.dist_px_sq);
+ retval = true;
+ }
break;
}
default:
@@ -541,19 +930,23 @@ static bool snapEmpty(
}
static bool snapCamera(
- Scene *scene, Object *object, float obmat[4][4],
- const short snap_to, const bool is_persp,
- const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2],
+ const SnapObjectContext *sctx, Object *object, float obmat[4][4],
+ const short snap_to, const float mval[2], const enum eViewProj view_proj,
+ const float depth_range[2],
/* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
+ float *dist_px,
/* return args */
float r_loc[3], float *UNUSED(r_no))
{
+ Scene *scene = sctx->scene;
+
+ PreDefProject projectdefs;
+ precalc_project(&projectdefs, sctx->v3d_data.ar, *dist_px, NULL);
+
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_origin_local[3], ray_normal_local[3];
if (clip == NULL) {
return retval;
@@ -584,9 +977,6 @@ static bool snapCamera(
reconstructed_camera_imat[4][4];
float (*vertex_obmat)[4];
- copy_v3_v3(ray_origin_local, ray_origin);
- 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);
@@ -603,26 +993,16 @@ static bool snapCamera(
copy_v3_v3(bundle_pos, track->bundle_pos);
if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
- mul_m4_v3(orig_camera_imat, ray_origin_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_origin_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
vertex_obmat = obmat;
}
- float ob_scale[3];
- mat4_to_size(ob_scale, vertex_obmat);
-
- retval |= test_vert(
- bundle_pos, NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
-
- mul_m4_v3(vertex_obmat, r_loc);
+ mul_m4_v3(vertex_obmat, bundle_pos);
+ retval |= test_projected_vert_dist(
+ &projectdefs, bundle_pos, view_proj, mval, depth_range, r_loc);
}
}
@@ -632,7 +1012,11 @@ static bool snapCamera(
break;
}
- return retval;
+ if (retval) {
+ *dist_px = sqrtf(projectdefs.dist_px_sq);
+ return true;
+ }
+ return false;
}
static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
@@ -643,44 +1027,45 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
struct NearestDM_Data {
void *bvhdata;
- bool is_persp;
- const float *ray_depth_range;
-
+ const float *depth_range;
float *ray_depth;
};
-static void test_vert_depth_cb(
+static void test_vert_ray_dist_cb(
void *userdata, const float origin[3], const float dir[3],
const float scale[3], int index, BVHTreeNearest *nearest)
{
struct NearestDM_Data *ndata = userdata;
- const BVHTreeFromMesh *data = ndata->bvhdata;
- const MVert *vert = data->vert + index;
+ const struct BVHTreeFromMeshType *data = ndata->bvhdata;
+
+ const float *co = get_vert_co(data, index);
- if (test_vert(
- vert->co, NULL, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp,
- ndata->ray_depth, &nearest->dist_sq,
- nearest->co, NULL))
+ if (test_vert_dist(
+ co, origin, dir, ndata->depth_range,
+ scale, ndata->ray_depth, &nearest->dist_sq,
+ nearest->co))
{
- normal_short_to_float_v3(nearest->no, vert->no);
+ copy_vert_no(data, index, nearest->no);
nearest->index = index;
}
}
-static void test_edge_depth_cb(
+static void test_edge_ray_dist_cb(
void *userdata, const float origin[3], const float dir[3],
const float scale[3], int index, BVHTreeNearest *nearest)
{
struct NearestDM_Data *ndata = userdata;
- const BVHTreeFromMesh *data = ndata->bvhdata;
- const MVert *vert = data->vert;
- const MEdge *edge = data->edge + index;
-
- if (test_edge(
- vert[edge->v1].co, vert[edge->v2].co, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp,
- ndata->ray_depth, &nearest->dist_sq,
- nearest->co, nearest->no))
+ BVHTreeFromMeshType *data = ndata->bvhdata;
+
+ const float *v_pair[2];
+ get_edge_verts(data, index, v_pair);
+
+ if (test_edge_dist(
+ v_pair[0], v_pair[1], origin, dir, ndata->depth_range,
+ scale, ndata->ray_depth, &nearest->dist_sq,
+ nearest->co))
{
+ sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]);
nearest->index = index;
}
}
@@ -688,10 +1073,11 @@ static void test_edge_depth_cb(
static bool snapDerivedMesh(
SnapObjectContext *sctx,
Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index,
- const short snap_to, const bool is_persp, bool do_bb,
- const float ray_origin[3], const float ray_start[3], const float ray_normal[3], const float ray_depth_range[2],
+ const short snap_to, const float mval[2], const enum eViewProj view_proj, bool do_bb,
+ const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
+ const float depth_range[2],
/* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
+ float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float r_no[3], int *r_index,
ListBase *r_hit_list)
@@ -703,7 +1089,7 @@ static bool snapDerivedMesh(
return retval;
}
}
- if (snap_to == SCE_SNAP_MODE_EDGE) {
+ else if (snap_to == SCE_SNAP_MODE_EDGE) {
if (dm->getNumEdges(dm) == 0) {
return retval;
}
@@ -715,7 +1101,7 @@ static bool snapDerivedMesh(
}
{
- bool need_ray_start_correction_init = (snap_to == SCE_SNAP_MODE_FACE) && sctx->use_v3d && !is_persp;
+ bool need_ray_start_correction_init = (snap_to == SCE_SNAP_MODE_FACE) && (view_proj == VIEW_PROJ_ORTHO);
float imat[4][4];
float timat[3][3]; /* transpose inverse matrix for normals */
@@ -823,28 +1209,30 @@ static bool snapDerivedMesh(
}
}
+ if (!treedata || !treedata->tree) {
+ return retval;
+ }
+
if (snap_to == SCE_SNAP_MODE_FACE) {
/* 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 (sctx->use_v3d && !is_persp) { /* do_ray_start_correction */
+ if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
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.
*/
- if (treedata && treedata->tree != NULL) {
- BVHTreeNearest nearest;
- 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) {
- float dvec[3];
- sub_v3_v3v3(dvec, nearest.co, ray_start_local);
- len_diff = dot_v3v3(dvec, ray_normal_local);
- }
+ BVHTreeNearest nearest;
+ 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) {
+ float dvec[3];
+ sub_v3_v3v3(dvec, nearest.co, ray_start_local);
+ len_diff = dot_v3v3(dvec, ray_normal_local);
}
}
float ray_org_local[3];
@@ -856,8 +1244,7 @@ static bool snapDerivedMesh(
* 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 + ray_depth_range[0]);
+ madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0]);
local_depth -= len_diff;
}
else {
@@ -874,24 +1261,19 @@ static bool snapDerivedMesh(
data.local_scale = local_scale;
data.ob = ob;
data.ob_uuid = ob_index;
- data.dm = dm;
data.hit_list = r_hit_list;
data.retval = retval;
BLI_bvhtree_ray_cast_all(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- *ray_depth, raycast_all_cb, &data);
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ *ray_depth, raycast_all_cb, &data);
retval = data.retval;
}
else {
- BVHTreeRayHit hit;
+ BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
- hit.index = -1;
- hit.dist = local_depth;
-
- if (treedata->tree &&
- BLI_bvhtree_ray_cast(
+ if (BLI_bvhtree_ray_cast(
treedata->tree, ray_start_local, ray_normal_local, 0.0f,
&hit, treedata->raycast_callback, treedata) != -1)
{
@@ -900,12 +1282,15 @@ static bool snapDerivedMesh(
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);
+
+ if (r_no) {
+ copy_v3_v3(r_no, hit.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
retval = true;
@@ -917,51 +1302,78 @@ static bool snapDerivedMesh(
}
}
else {
- /* Vert & edge use nearly identical logic. */
- BLI_assert(ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE));
+ const ARegion *ar = sctx->v3d_data.ar;
float ray_org_local[3];
-
copy_v3_v3(ray_org_local, ray_origin);
mul_m4_v3(imat, ray_org_local);
- BVHTreeNearest nearest;
+ BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH};
- nearest.index = -1;
- nearest.dist_sq = *dist_to_ray_sq;
+ if (view_proj == VIEW_PROJ_PERSP) {
+ Object_Nearest2dPrecalc neasrest_precalc;
+ neasrest_precalc.userdata = &treedata_type;
+ neasrest_precalc.index = -1;
- struct NearestDM_Data userdata;
- userdata.bvhdata = treedata;
- userdata.is_persp = is_persp;
- userdata.ray_depth_range = ray_depth_range;
- userdata.ray_depth = ray_depth;
+ nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat,
+ ray_org_local, ray_normal_local, mval, depth_range);
- float ob_scale[3];
- mat4_to_size(ob_scale, obmat);
+ BVHTree_WalkLeafCallback cb_walk_leaf =
+ (snap_to == SCE_SNAP_MODE_VERTEX) ?
+ cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
- BVHTree_NearestToRayCallback callback =
- (snap_to == SCE_SNAP_MODE_VERTEX) ?
- test_vert_depth_cb : test_edge_depth_cb;
+ BLI_bvhtree_walk_dfs(
+ treedata->tree,
+ cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc);
- if (treedata->tree &&
- (is_persp ?
- BLI_bvhtree_find_nearest_to_ray_angle(
- treedata->tree, ray_org_local, ray_normal_local,
- true, ob_scale, &nearest, callback, &userdata) :
- BLI_bvhtree_find_nearest_to_ray(
- treedata->tree, ray_org_local, ray_normal_local,
- true, ob_scale, &nearest, callback, &userdata)) != -1)
- {
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- copy_v3_v3(r_no, nearest.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
+ if (neasrest_precalc.index != -1) {
+ copy_v3_v3(r_loc, neasrest_precalc.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, neasrest_precalc.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+ *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq);
+
+ retval = true;
}
- *dist_to_ray_sq = nearest.dist_sq;
+ }
+ else {
+ BVHTreeNearest nearest;
- retval = true;
+ nearest.index = -1;
+ float dist_3d = dist_px_to_dist3d_or_tangent(ar, *dist_px);
+ nearest.dist_sq = SQUARE(dist_3d);
+
+
+ float ob_scale[3];
+ mat4_to_size(ob_scale, obmat);
+
+ struct NearestDM_Data userdata;
+ userdata.bvhdata = &treedata_type;
+ userdata.depth_range = depth_range;
+ userdata.ray_depth = ray_depth;
+
+ BVHTree_NearestToRayCallback cb_test_ray_dist =
+ (snap_to == SCE_SNAP_MODE_VERTEX) ?
+ test_vert_ray_dist_cb : test_edge_ray_dist_cb;
+
+ if (BLI_bvhtree_find_nearest_to_ray(
+ treedata->tree, ray_org_local, ray_normal_local,
+ false, ob_scale, &nearest, cb_test_ray_dist, &userdata) != -1)
+ {
+ copy_v3_v3(r_loc, nearest.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, nearest.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+ *dist_px *= sqrtf(nearest.dist_sq) / dist_3d;
+
+ retval = true;
+ }
}
}
@@ -975,47 +1387,14 @@ static bool snapDerivedMesh(
return retval;
}
-static void test_bmvert_depth_cb(
- void *userdata, const float origin[3], const float dir[3],
- const float scale[3], int index, BVHTreeNearest *nearest)
-{
- struct NearestDM_Data *ndata = userdata;
- const BMEditMesh *em = ndata->bvhdata;
- BMVert *eve = BM_vert_at_index(em->bm, index);
-
- if (test_vert(
- eve->co, eve->no, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp,
- ndata->ray_depth, &nearest->dist_sq,
- nearest->co, nearest->no))
- {
- nearest->index = index;
- }
-}
-
-static void test_bmedge_depth_cb(
- void *userdata, const float origin[3], const float dir[3],
- const float scale[3], int index, BVHTreeNearest *nearest)
-{
- struct NearestDM_Data *ndata = userdata;
- const BMEditMesh *em = ndata->bvhdata;
- BMEdge *eed = BM_edge_at_index(em->bm, index);
-
- if (test_edge(
- eed->v1->co, eed->v2->co, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp,
- ndata->ray_depth, &nearest->dist_sq,
- nearest->co, nearest->no))
- {
- nearest->index = index;
- }
-}
-
static bool snapEditMesh(
SnapObjectContext *sctx,
Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index,
- const short snap_to, const bool is_persp,
- const float ray_origin[3], const float ray_start[3], const float ray_normal[3], const float ray_depth_range[2],
+ const short snap_to, const float mval[2], const enum eViewProj view_proj,
+ const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
+ const float depth_range[2],
/* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
+ float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float r_no[3], int *r_index,
ListBase *r_hit_list)
@@ -1143,6 +1522,10 @@ static bool snapEditMesh(
}
}
+ if (!treedata || !treedata->tree) {
+ return retval;
+ }
+
if (snap_to == SCE_SNAP_MODE_FACE) {
float ray_start_local[3];
copy_v3_v3(ray_start_local, ray_start);
@@ -1160,35 +1543,32 @@ static bool snapEditMesh(
* Note also ar might be null (see T38435), in this case we assume ray_start is ok!
*/
float len_diff = 0.0f;
- if (sctx->use_v3d && !is_persp) { /* do_ray_start_correction */
+ if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
/* We *need* a reasonably valid len_diff in this case.
* Use BHVTree to find the closest face from ray_start_local.
*/
- if (treedata && treedata->tree != NULL) {
- BVHTreeNearest nearest;
- nearest.index = -1;
- nearest.dist_sq = FLT_MAX;
- /* Compute and store result. */
- if (BLI_bvhtree_find_nearest(
- treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1)
- {
- float dvec[3];
- sub_v3_v3v3(dvec, nearest.co, ray_start_local);
- len_diff = dot_v3v3(dvec, ray_normal_local);
- 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 + ray_depth_range[0]);
- local_depth -= len_diff;
- }
+ BVHTreeNearest nearest;
+ nearest.index = -1;
+ nearest.dist_sq = FLT_MAX;
+ /* Compute and store result. */
+ if (BLI_bvhtree_find_nearest(
+ treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1)
+ {
+ float dvec[3];
+ sub_v3_v3v3(dvec, nearest.co, ray_start_local);
+ len_diff = dot_v3v3(dvec, ray_normal_local);
+ 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 + depth_range[0]);
+ local_depth -= len_diff;
}
}
if (r_hit_list) {
@@ -1202,7 +1582,6 @@ static bool snapEditMesh(
data.local_scale = local_scale;
data.ob = ob;
data.ob_uuid = ob_index;
- data.dm = NULL;
data.hit_list = r_hit_list;
data.retval = retval;
@@ -1213,13 +1592,9 @@ static bool snapEditMesh(
retval = data.retval;
}
else {
- BVHTreeRayHit hit;
+ BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
- hit.index = -1;
- hit.dist = local_depth;
-
- if (treedata->tree &&
- BLI_bvhtree_ray_cast(
+ if (BLI_bvhtree_ray_cast(
treedata->tree, ray_start_local, ray_normal_local, 0.0f,
&hit, treedata->raycast_callback, treedata) != -1)
{
@@ -1228,12 +1603,15 @@ static bool snapEditMesh(
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);
+
+ if (r_no) {
+ copy_v3_v3(r_no, hit.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
retval = true;
@@ -1245,51 +1623,78 @@ static bool snapEditMesh(
}
}
else {
- /* Vert & edge use nearly identical logic. */
- BLI_assert(ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE));
+ const ARegion *ar = sctx->v3d_data.ar;
float ray_org_local[3];
-
copy_v3_v3(ray_org_local, ray_origin);
mul_m4_v3(imat, ray_org_local);
- BVHTreeNearest nearest;
+ BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH};
- nearest.index = -1;
- nearest.dist_sq = *dist_to_ray_sq;
+ if (view_proj == VIEW_PROJ_PERSP) {
+ Object_Nearest2dPrecalc neasrest_precalc;
+ neasrest_precalc.userdata = &treedata_type;
+ neasrest_precalc.index = -1;
- struct NearestDM_Data userdata;
- userdata.bvhdata = em;
- userdata.is_persp = is_persp;
- userdata.ray_depth_range = ray_depth_range;
- userdata.ray_depth = ray_depth;
+ nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat,
+ ray_org_local, ray_normal_local, mval, depth_range);
- float ob_scale[3];
- mat4_to_size(ob_scale, obmat);
+ BVHTree_WalkLeafCallback cb_walk_leaf =
+ (snap_to == SCE_SNAP_MODE_VERTEX) ?
+ cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
- BVHTree_NearestToRayCallback callback =
- (snap_to == SCE_SNAP_MODE_VERTEX) ?
- test_bmvert_depth_cb : test_bmedge_depth_cb;
+ BLI_bvhtree_walk_dfs(
+ treedata->tree,
+ cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc);
- if (treedata->tree &&
- (is_persp ?
- BLI_bvhtree_find_nearest_to_ray_angle(
- treedata->tree, ray_org_local, ray_normal_local,
- false, ob_scale, &nearest, callback, &userdata) :
- BLI_bvhtree_find_nearest_to_ray(
- treedata->tree, ray_org_local, ray_normal_local,
- false, ob_scale, &nearest, callback, &userdata)) != -1)
- {
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- copy_v3_v3(r_no, nearest.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
+ if (neasrest_precalc.index != -1) {
+ copy_v3_v3(r_loc, neasrest_precalc.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, neasrest_precalc.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+ *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq);
+
+ retval = true;
}
- *dist_to_ray_sq = nearest.dist_sq;
+ }
+ else {
+ BVHTreeNearest nearest;
- retval = true;
+ nearest.index = -1;
+ float dist_3d = dist_px_to_dist3d_or_tangent(ar, *dist_px);
+ nearest.dist_sq = SQUARE(dist_3d);
+
+
+ float ob_scale[3];
+ mat4_to_size(ob_scale, obmat);
+
+ struct NearestDM_Data userdata;
+ userdata.bvhdata = &treedata_type;
+ userdata.depth_range = depth_range;
+ userdata.ray_depth = ray_depth;
+
+ BVHTree_NearestToRayCallback cb_test_ray_dist =
+ (snap_to == SCE_SNAP_MODE_VERTEX) ?
+ test_vert_ray_dist_cb : test_edge_ray_dist_cb;
+
+ if (BLI_bvhtree_find_nearest_to_ray(
+ treedata->tree, ray_org_local, ray_normal_local,
+ false, ob_scale, &nearest, cb_test_ray_dist, &userdata) != -1)
+ {
+ copy_v3_v3(r_loc, nearest.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, nearest.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+ *dist_px *= sqrtf(nearest.dist_sq) / dist_3d;
+
+ retval = true;
+ }
}
}
@@ -1305,26 +1710,28 @@ static bool snapEditMesh(
/**
* \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping;
- * \param ray_depth_range:
- * - 0: distance from the ray_origin to the clipping plane min (can be negative).
- * - 1: maximum distance, elements outside this are ignored.
- * \param ray_depth: maximum depth allowed for r_co.
*
* \note Duplicate args here are documented at #snapObjectsRay
*/
static bool snapObject(
SnapObjectContext *sctx,
Object *ob, float obmat[4][4], const unsigned int ob_index,
- bool use_obedit, const short snap_to,
- const float ray_origin[3], const float ray_start[3], const float ray_normal[3], const float ray_depth_range[2],
+ bool use_obedit, const short snap_to, const float mval[2],
+ const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
+ const float depth_range[2],
/* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
+ float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4],
ListBase *r_hit_list)
{
- const bool is_persp = sctx->use_v3d && ((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp;
+ const enum eViewProj view_proj =
+ ((sctx->use_v3d == false) || (mval == NULL)) ? VIEW_PROJ_NONE :
+ (((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO);
+
+ const ARegion *ar = sctx->v3d_data.ar;
+
bool retval = false;
if (ob->type == OB_MESH) {
@@ -1334,9 +1741,9 @@ static bool snapObject(
em = BKE_editmesh_from_object(ob);
retval = snapEditMesh(
sctx, ob, em, obmat, ob_index,
- snap_to, is_persp,
- ray_origin, ray_start, ray_normal, ray_depth_range,
- ray_depth, dist_to_ray_sq,
+ snap_to, mval, view_proj,
+ ray_origin, ray_start, ray_normal, depth_range,
+ ray_depth, dist_px,
r_loc, r_no, r_index,
r_hit_list);
}
@@ -1353,42 +1760,43 @@ static bool snapObject(
}
retval = snapDerivedMesh(
sctx, ob, dm, obmat, ob_index,
- snap_to, is_persp, true,
- ray_origin, ray_start, ray_normal, ray_depth_range,
- ray_depth, dist_to_ray_sq,
+ snap_to, mval, view_proj, true,
+ ray_origin, ray_start, ray_normal, depth_range,
+ ray_depth, dist_px,
r_loc, r_no,
r_index, r_hit_list);
dm->release(dm);
}
}
- else if (ob->type == OB_ARMATURE) {
- retval = snapArmature(
- ob, ob->data, obmat, snap_to, is_persp,
- ray_origin, ray_normal, ray_depth_range,
- ray_depth, dist_to_ray_sq,
- r_loc, r_no);
- }
- else if (ob->type == OB_CURVE) {
- retval = snapCurve(
- ob, ob->data, obmat, snap_to, is_persp,
- ray_origin, ray_normal, ray_depth_range,
- ray_depth, dist_to_ray_sq,
- r_loc, r_no);
- }
- else if (ob->type == OB_EMPTY) {
- retval = snapEmpty(
- ob, obmat, snap_to, is_persp,
- ray_origin, ray_normal, ray_depth_range,
- ray_depth, dist_to_ray_sq,
- r_loc, r_no);
- }
- else if (ob->type == OB_CAMERA) {
- retval = snapCamera(
- sctx->scene, ob, obmat, snap_to, is_persp,
- ray_origin, ray_normal, ray_depth_range,
- ray_depth, dist_to_ray_sq,
- r_loc, r_no);
+ else if (snap_to != SCE_SNAP_MODE_FACE) {
+ if (ob->type == OB_ARMATURE) {
+ retval = snapArmature(
+ ar, ob, ob->data, obmat, snap_to, ray_origin, ray_normal,
+ mval, view_proj, depth_range, dist_px,
+ r_loc, r_no);
+ }
+ else if (ob->type == OB_CURVE) {
+ retval = snapCurve(
+ ar, ob, ob->data, obmat, snap_to, mval, view_proj,
+ depth_range,
+ dist_px,
+ r_loc, r_no);
+ }
+ else if (ob->type == OB_EMPTY) {
+ retval = snapEmpty(
+ ar, ob, obmat, snap_to, mval, view_proj,
+ depth_range,
+ dist_px,
+ r_loc, r_no);
+ }
+ else if (ob->type == OB_CAMERA) {
+ retval = snapCamera(
+ sctx, ob, obmat, snap_to, mval, view_proj,
+ depth_range,
+ dist_px,
+ r_loc, r_no);
+ }
}
if (retval) {
@@ -1414,16 +1822,18 @@ static bool snapObject(
* \param snap_select: from enum SnapSelect.
*
* \param use_object_edit_cage: Uses the coordinates of BMesh (if any) to do the snapping.
+ * \param mval: Mouse coords.
+ * When NULL, ray-casting is handled without any projection matrix correction.
* \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min.
* \param ray_start: ray_origin moved for the start clipping plane (clip_min).
* \param ray_normal: Unit length direction of the ray.
+ * \param depth_range: distances of clipe plane min and clip plane max;
*
* Read/Write Args
* ---------------
*
* \param ray_depth: maximum depth allowed for r_co, elements deeper than this value will be ignored.
- * \param dist_to_ray_sq: Real distance (3D) or Tangent (view cone radius at distance 1.0) squared.
- * resulting of the function #dist_px_to_dist3d_or_tangent.
+ * \param dist_px: Maximum threshold distance (in pixels).
*
* Output Args
* -----------
@@ -1440,10 +1850,11 @@ static bool snapObject(
static bool snapObjectsRay(
SnapObjectContext *sctx,
const unsigned short snap_to, const SnapSelect snap_select,
- const bool use_object_edit_cage,
+ const bool use_object_edit_cage, const float mval[2],
const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
+ const float depth_range[2],
/* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
+ float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4],
@@ -1451,14 +1862,6 @@ static bool snapObjectsRay(
{
bool retval = false;
- float dvec[3];
- sub_v3_v3v3(dvec, ray_start, ray_origin);
-
- const float ray_depth_range[2] = {
- dot_v3v3(dvec, ray_normal),
- *ray_depth,
- };
-
unsigned int ob_index = 0;
Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL;
Base *base_act = sctx->scene->basact;
@@ -1493,9 +1896,9 @@ static bool snapObjectsRay(
retval |= snapObject(
sctx, dupli_snap, dupli_ob->mat, ob_index++,
- use_obedit_dupli, snap_to,
- ray_origin, ray_start, ray_normal, ray_depth_range,
- ray_depth, dist_to_ray_sq,
+ use_obedit_dupli, snap_to, mval,
+ ray_origin, ray_start, ray_normal, depth_range,
+ ray_depth, dist_px,
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
@@ -1507,9 +1910,9 @@ static bool snapObjectsRay(
retval |= snapObject(
sctx, ob_snap, ob->obmat, ob_index++,
- use_obedit, snap_to,
- ray_origin, ray_start, ray_normal, ray_depth_range,
- ray_depth, dist_to_ray_sq,
+ use_obedit, snap_to, mval,
+ ray_origin, ray_start, ray_normal, depth_range,
+ ray_depth, dist_px,
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
}
@@ -1616,13 +2019,12 @@ bool ED_transform_snap_object_project_ray_ex(
float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4])
{
- float dist_to_ray_sq = 0.0f;
-
+ const float depth_range[2] = {0.0f, FLT_MAX};
return snapObjectsRay(
sctx,
- snap_to, params->snap_select, params->use_object_edit_cage,
- ray_start, ray_start, ray_normal,
- ray_depth, &dist_to_ray_sq,
+ snap_to, params->snap_select, params->use_object_edit_cage, NULL,
+ ray_start, ray_start, ray_normal, depth_range,
+ ray_depth, NULL,
r_loc, r_no, r_index, r_ob, r_obmat, NULL);
}
@@ -1641,8 +2043,7 @@ bool ED_transform_snap_object_project_ray_all(
float ray_depth, bool sort,
ListBase *r_hit_list)
{
- float dist_to_ray_sq = 0.0f;
-
+ const float depth_range[2] = {0.0f, FLT_MAX};
if (ray_depth == -1.0f) {
ray_depth = BVH_RAYCAST_DIST_MAX;
}
@@ -1653,9 +2054,9 @@ bool ED_transform_snap_object_project_ray_all(
bool retval = snapObjectsRay(
sctx,
- snap_to, params->snap_select, params->use_object_edit_cage,
- ray_start, ray_start, ray_normal,
- &ray_depth, &dist_to_ray_sq,
+ snap_to, params->snap_select, params->use_object_edit_cage, NULL,
+ ray_start, ray_start, ray_normal, depth_range,
+ &ray_depth, NULL,
NULL, NULL, NULL, NULL, NULL,
r_hit_list);
@@ -1710,11 +2111,6 @@ bool ED_transform_snap_object_project_ray(
ray_depth = &ray_depth_fallback;
}
- float no_fallback[3];
- if (r_no == NULL) {
- r_no = no_fallback;
- }
-
return transform_snap_context_project_ray_impl(
sctx,
params,
@@ -1733,11 +2129,6 @@ static bool transform_snap_context_project_view3d_mixed_impl(
float ray_depth = BVH_RAYCAST_DIST_MAX;
bool is_hit = false;
- float r_no_dummy[3];
- if (r_no == NULL) {
- r_no = r_no_dummy;
- }
-
const int elem_type[3] = {SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE, SCE_SNAP_MODE_FACE};
BLI_assert(snap_to_flag != 0);
@@ -1764,21 +2155,6 @@ static bool transform_snap_context_project_view3d_mixed_impl(
}
/**
- * From a threshold (maximum distance to snap in pixels) returns:
- *
- * - The *real* distance (3D) if you are in orthographic-view.
- * - The *tangent* (view cone radius at distance 1.0) if you are in perspective-view.
- */
-static float dist_px_to_dist3d_or_tangent(const ARegion *ar, const float dist_px)
-{
- const RegionView3D *rv3d = ar->regiondata;
- if (ar->winx >= ar->winy)
- return 2 * (dist_px / ar->winx) / rv3d->winmat[0][0];
- else
- return 2 * (dist_px / ar->winy) / rv3d->winmat[1][1];
-}
-
-/**
* Convenience function for performing snapping.
*
* Given a 2D region value, snap to vert/edge/face.
@@ -1814,55 +2190,37 @@ bool ED_transform_snap_object_project_view3d_ex(
float *ray_depth,
float r_loc[3], float r_no[3], int *r_index)
{
- float ray_start[3], ray_normal[3], ray_origin[3];
+ float ray_origin[3], ray_start[3], ray_normal[3], depth_range[2], ray_end[3];
- float ray_depth_fallback;
- if (ray_depth == NULL) {
- ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
- ray_depth = &ray_depth_fallback;
- }
+ const ARegion *ar = sctx->v3d_data.ar;
+ const RegionView3D *rv3d = ar->regiondata;
- if (!ED_view3d_win_to_ray_ex(
- sctx->v3d_data.ar, sctx->v3d_data.v3d,
- mval, ray_origin, ray_normal, ray_start, true))
- {
+ ED_view3d_win_to_origin(ar, mval, ray_origin);
+ ED_view3d_win_to_vector(ar, mval, ray_normal);
+
+ ED_view3d_clip_range_get(
+ sctx->v3d_data.v3d, sctx->v3d_data.ar->regiondata,
+ &depth_range[0], &depth_range[1], false);
+
+ madd_v3_v3v3fl(ray_start, ray_origin, ray_normal, depth_range[0]);
+ madd_v3_v3v3fl(ray_end, ray_origin, ray_normal, depth_range[1]);
+
+ if (!ED_view3d_clip_segment(rv3d, ray_start, ray_end)) {
return false;
}
- float radius, dist_to_ray_sq = 0.0f;
- if (dist_px) {
- radius = dist_px_to_dist3d_or_tangent(sctx->v3d_data.ar, *dist_px);
- /**
- * Workaround to use of cone (Instead of project the radius on view plane):
- * In perspective view, the radius of the cone may decrease depending on the ray direction.
- * This is more evident with small values of the `Viewport lens angle`.
- * The threshold becomes distorted that way.
- */
- RegionView3D *rv3d = sctx->v3d_data.ar->regiondata;
- if (rv3d->is_persp) {
- float view_dir[3];
- negate_v3_v3(view_dir, rv3d->viewinv[2]);
- normalize_v3(view_dir);
- radius *= dot_v3v3(ray_normal, view_dir);
- }
-
- dist_to_ray_sq = SQUARE(radius);
+ float ray_depth_fallback;
+ if (ray_depth == NULL) {
+ ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
+ ray_depth = &ray_depth_fallback;
}
- if (snapObjectsRay(
+ return snapObjectsRay(
sctx,
snap_to, params->snap_select, params->use_object_edit_cage,
- ray_origin, ray_start, ray_normal,
- ray_depth, &dist_to_ray_sq,
- r_loc, r_no, r_index, NULL, NULL, NULL))
- {
- if (dist_px) {
- *dist_px *= sqrtf(dist_to_ray_sq) / radius;
- }
- return true;
- }
-
- return false;
+ mval, ray_origin, ray_start, ray_normal, depth_range,
+ ray_depth, dist_px,
+ r_loc, r_no, r_index, NULL, NULL, NULL);
}
bool ED_transform_snap_object_project_view3d(