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:
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/armature/pose_lib.c2
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h2
-rw-r--r--source/blender/editors/interface/interface_regions.c4
-rw-r--r--source/blender/editors/interface/interface_utils.c11
-rw-r--r--source/blender/editors/io/io_alembic.c18
-rw-r--r--source/blender/editors/io/io_cache.c30
-rw-r--r--source/blender/editors/mesh/editmesh_select.c6
-rw-r--r--source/blender/editors/object/object_add.c3
-rw-r--r--source/blender/editors/render/render_preview.c2
-rw-r--r--source/blender/editors/screen/screen_edit.c1
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c6
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c2
-rw-r--r--source/blender/editors/space_image/image_ops.c13
-rw-r--r--source/blender/editors/space_info/info_ops.c1
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c7
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c9
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c6
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c10
-rw-r--r--source/blender/editors/space_view3d/drawobject.c10
-rw-r--r--source/blender/editors/transform/transform.c17
-rw-r--r--source/blender/editors/transform/transform_conversions.c150
-rw-r--r--source/blender/editors/transform/transform_orientations.c42
-rw-r--r--source/blender/editors/transform/transform_snap_object.c1348
-rw-r--r--source/blender/editors/util/undo.c8
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c9
25 files changed, 1068 insertions, 649 deletions
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index e3c64b523b1..25f1b282f14 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -328,7 +328,7 @@ static int poselib_sanitize_exec(bContext *C, wmOperator *op)
/* add pose to poselib */
marker = MEM_callocN(sizeof(TimeMarker), "ActionMarker");
- BLI_strncpy(marker->name, "Pose", sizeof(marker->name));
+ BLI_snprintf(marker->name, sizeof(marker->name), "F%d Pose", (int)ak->cfra);
marker->frame = (int)ak->cfra;
marker->flag = -1;
diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h
index 6eaae49912c..8066adf55ce 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -84,7 +84,6 @@ void ED_transform_snap_object_context_set_editmesh_callbacks(
bool ED_transform_snap_object_project_ray_ex(
struct SnapObjectContext *sctx,
- const unsigned short snap_to,
const struct SnapObjectParams *params,
const float ray_start[3], const float ray_normal[3], float *ray_depth,
/* return args */
@@ -98,7 +97,6 @@ bool ED_transform_snap_object_project_ray(
bool ED_transform_snap_object_project_ray_all(
SnapObjectContext *sctx,
- const unsigned short snap_to,
const struct SnapObjectParams *params,
const float ray_start[3], const float ray_normal[3],
float ray_depth, bool sort,
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 534bd4278ca..5ed94474726 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -2099,9 +2099,11 @@ static void ui_update_color_picker_buts_rgb(uiBlock *block, ColorPicker *cpicker
continue;
if (bt->rnaprop) {
-
ui_but_v3_set(bt, rgb);
+ /* original button that created the color picker already does undo
+ * push, so disable it on RNA buttons in the color picker block */
+ UI_but_flag_disable(bt, UI_BUT_UNDO);
}
else if (STREQ(bt->str, "Hex: ")) {
float rgb_gamma[3];
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 636b7e4e9ce..cf16cc9f50d 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -380,6 +380,17 @@ uiButStore *UI_butstore_create(uiBlock *block)
void UI_butstore_free(uiBlock *block, uiButStore *bs_handle)
{
+ /* Workaround for button store being moved into new block,
+ * which then can't use the previous buttons state ('ui_but_update_from_old_block' fails to find a match),
+ * keeping the active button in the old block holding a reference to the button-state in the new block: see T49034.
+ *
+ * Ideally we would manage moving the 'uiButStore', keeping a correct state.
+ * All things considered this is the most straightforward fix - Campbell.
+ */
+ if (block != bs_handle->block && bs_handle->block != NULL) {
+ block = bs_handle->block;
+ }
+
BLI_freelistN(&bs_handle->items);
BLI_remlink(&block->butstore, bs_handle);
diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c
index fb20d9f3caa..ca4ab30a08d 100644
--- a/source/blender/editors/io/io_alembic.c
+++ b/source/blender/editors/io/io_alembic.c
@@ -31,6 +31,9 @@
# include "BLI_winstuff.h"
#endif
+#include <string.h>
+#include <errno.h>
+
#include "MEM_guardedalloc.h"
#include "DNA_mesh_types.h"
@@ -417,9 +420,20 @@ static int get_sequence_len(char *filename, int *ofs)
}
char path[FILE_MAX];
+ BLI_path_abs(filename, G.main->name);
BLI_split_dir_part(filename, path, FILE_MAX);
+ if (path[0] == '\0') {
+ /* The filename had no path, so just use the blend file path. */
+ BLI_split_dir_part(G.main->name, path, FILE_MAX);
+ }
+
DIR *dir = opendir(path);
+ if (dir == NULL) {
+ fprintf(stderr, "Error opening directory '%s': %s\n",
+ path, errno ? strerror(errno) : "unknown error");
+ return -1;
+ }
const char *ext = ".abc";
const char *basename = BLI_path_basename(filename);
@@ -523,6 +537,10 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op)
if (is_sequence) {
sequence_len = get_sequence_len(filename, &offset);
+ if (sequence_len < 0) {
+ BKE_report(op->reports, RPT_ERROR, "Unable to determine ABC sequence length");
+ return OPERATOR_CANCELLED;
+ }
}
bool ok = ABC_import(C, filename, scale, is_sequence, set_frame_range,
diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c
index af6f55d7a64..a5e90ebbe7a 100644
--- a/source/blender/editors/io/io_cache.c
+++ b/source/blender/editors/io/io_cache.c
@@ -97,22 +97,24 @@ static int cachefile_open_exec(bContext *C, wmOperator *op)
BLI_strncpy(cache_file->filepath, filename, FILE_MAX);
BKE_cachefile_reload(bmain, cache_file);
- /* hook into UI */
- PropertyPointerRNA *pprop = op->customdata;
-
- if (pprop->prop) {
- /* when creating new ID blocks, use is already 1, but RNA
- * pointer se also increases user, so this compensates it */
- id_us_min(&cache_file->id);
-
- PointerRNA idptr;
- RNA_id_pointer_create(&cache_file->id, &idptr);
- RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
- RNA_property_update(C, &pprop->ptr, pprop->prop);
+ /* Will be set when running invoke, not exec directly. */
+ if (op->customdata != NULL) {
+ /* hook into UI */
+ PropertyPointerRNA *pprop = op->customdata;
+ if (pprop->prop) {
+ /* when creating new ID blocks, use is already 1, but RNA
+ * pointer se also increases user, so this compensates it */
+ id_us_min(&cache_file->id);
+
+ PointerRNA idptr;
+ RNA_id_pointer_create(&cache_file->id, &idptr);
+ RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
+ RNA_property_update(C, &pprop->ptr, pprop->prop);
+ }
+
+ MEM_freeN(op->customdata);
}
- MEM_freeN(op->customdata);
-
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index a6de1b284b7..68bd8ff27b1 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -446,6 +446,9 @@ BMVert *EDBM_vert_find_nearest_ex(
unsigned int index;
BMVert *eve;
+ /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
+ ED_view3d_backbuf_validate(vc);
+
index = ED_view3d_backbuf_sample_rect(
vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test);
eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
@@ -630,7 +633,8 @@ BMEdge *EDBM_edge_find_nearest_ex(
float dist_test = 0.0f;
unsigned int index;
BMEdge *eed;
-
+
+ /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
ED_view3d_backbuf_validate(vc);
index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test);
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index a901560079a..b5a9c4e9e5b 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1464,8 +1464,6 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
}
if (ob_dst->parent) {
- invert_m4_m4(ob_dst->parentinv, dob->mat);
-
/* note, this may be the parent of other objects, but it should
* still work out ok */
BKE_object_apply_mat4(ob_dst, dob->mat, false, true);
@@ -1486,7 +1484,6 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
ob_dst->partype = PAROBJECT;
/* similer to the code above, see comments */
- invert_m4_m4(ob_dst->parentinv, dob->mat);
BKE_object_apply_mat4(ob_dst, dob->mat, false, true);
DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB);
}
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index fa18b82507e..35d772afae7 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -1180,7 +1180,7 @@ void ED_preview_icon_render(Main *bmain, Scene *scene, ID *id, unsigned int *rec
ip.bmain = bmain;
ip.scene = scene;
- ip.owner = id;
+ ip.owner = BKE_previewimg_id_ensure(id);
ip.id = id;
icon_preview_add_size(&ip, rect, sizex, sizey);
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 18f02aff482..f469686b0b2 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -1228,6 +1228,7 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
winrct.ymax = winsize_y - 1;
/* header size depends on DPI, let's verify */
+ WM_window_set_dpi(win);
screen_refresh_headersizes();
screen_test_scale(win->screen, winsize_x, winsize_y);
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index d0f1cc99b8d..b43581170d0 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -3712,8 +3712,12 @@ static void project_paint_prepare_all_faces(
}
/* don't allow using the same inage for painting and stencilling */
- if (slot->ima == ps->stencil_ima)
+ if (slot->ima == ps->stencil_ima) {
+ /* While this shouldn't be used, face-winding reads all polys.
+ * It's less trouble to set all faces to valid UV's, avoiding NULL checks all over. */
+ ps->dm_mloopuv[lt->poly] = mloopuv_base;
continue;
+ }
tpage = slot->ima;
}
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 72de7e5c81c..1d67ac620b0 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -470,7 +470,7 @@ void buttons_texture_context_compute(const bContext *C, SpaceButs *sbuts)
}
else {
/* set one user as active based on active index */
- if (ct->index == BLI_listbase_count_ex(&ct->users, ct->index + 1))
+ if (ct->index >= BLI_listbase_count_ex(&ct->users, ct->index + 1))
ct->index = 0;
ct->user = BLI_findlink(&ct->users, ct->index);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 501a5a35899..a0d67626940 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1098,6 +1098,7 @@ static void image_open_cancel(bContext *UNUSED(C), wmOperator *op)
static void image_sequence_get_frame_ranges(PointerRNA *ptr, ListBase *frames_all)
{
char dir[FILE_MAXDIR];
+ const bool do_frame_range = RNA_boolean_get(ptr, "use_sequence_detection");
ImageFrameRange *frame_range = NULL;
RNA_string_get(ptr, "directory", dir);
@@ -1113,7 +1114,8 @@ static void image_sequence_get_frame_ranges(PointerRNA *ptr, ListBase *frames_al
frame->framenr = BLI_stringdec(filename, head, tail, &digits);
/* still in the same sequence */
- if ((frame_range != NULL) &&
+ if (do_frame_range &&
+ (frame_range != NULL) &&
(STREQLEN(base_head, head, FILE_MAX)) &&
(STREQLEN(base_tail, tail, FILE_MAX)))
{
@@ -1325,7 +1327,11 @@ static int image_open_exec(bContext *C, wmOperator *op)
iuser->frames = frame_seq_len;
iuser->sfra = 1;
iuser->framenr = 1;
- iuser->offset = frame_ofs - 1;
+ if (ima->source == IMA_SRC_MOVIE) {
+ iuser->offset = 0;
+ } else {
+ iuser->offset = frame_ofs - 1;
+ }
iuser->fie_ima = 2;
iuser->scene = scene;
BKE_image_init_imageuser(ima, iuser);
@@ -1448,6 +1454,9 @@ void IMAGE_OT_open(wmOperatorType *ot)
ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILES | WM_FILESEL_RELPATH,
FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+
+ RNA_def_boolean(ot->srna, "use_sequence_detection", true, "Detect Sequences",
+ "Automatically detect animated sequences in selected images (based on file names)");
}
/******************** Match movie length operator ********************/
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index 0e427623840..b87a0de23b9 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -162,7 +162,6 @@ static int pack_all_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
packAll(bmain, op->reports, true);
- G.fileflags |= G_AUTOPACK;
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 7e05c76b35b..18cc2a015e6 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -707,7 +707,12 @@ static eOLDrawState tree_element_active_pose(
{
Object *ob = (Object *)tselem->id;
Base *base = BKE_scene_base_find(scene, ob);
-
+
+ if (base == NULL) {
+ /* Armature not instantiated in current scene (e.g. inside an appended group...). */
+ return OL_DRAWSEL_NONE;
+ }
+
if (set != OL_SETSEL_NONE) {
if (scene->obedit)
ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index ec46c5df9a0..09a49f201d4 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -1080,6 +1080,12 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
PointerRNA pptr, propptr, *ptr = (PointerRNA *)idv;
PropertyRNA *prop, *iterprop;
PropertyType proptype;
+
+ /* Don't display arrays larger, weak but index is stored as a short,
+ * also the outliner isn't intended for editing such large data-sets. */
+ BLI_STATIC_ASSERT(sizeof(te->index) == 2, "Index is no longer short!");
+ const int tot_limit = SHRT_MAX;
+
int a, tot;
/* we do lazy build, for speed and to avoid infinite recusion */
@@ -1101,6 +1107,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
iterprop = RNA_struct_iterator_property(ptr->type);
tot = RNA_property_collection_length(ptr, iterprop);
+ CLAMP_MAX(tot, tot_limit);
/* auto open these cases */
if (!parent || (RNA_property_type(parent->directdata)) == PROP_POINTER)
@@ -1147,6 +1154,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
}
else if (proptype == PROP_COLLECTION) {
tot = RNA_property_collection_length(ptr, prop);
+ CLAMP_MAX(tot, tot_limit);
if (TSELEM_OPEN(tselem, soops)) {
for (a = 0; a < tot; a++) {
@@ -1159,6 +1167,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
}
else if (ELEM(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
tot = RNA_property_array_length(ptr, prop);
+ CLAMP_MAX(tot, tot_limit);
if (TSELEM_OPEN(tselem, soops)) {
for (a = 0; a < tot; a++)
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 3ae4a233353..e63569ac386 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -3512,7 +3512,7 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
bool proxy_50 = RNA_boolean_get(op->ptr, "proxy_50");
bool proxy_75 = RNA_boolean_get(op->ptr, "proxy_75");
bool proxy_100 = RNA_boolean_get(op->ptr, "proxy_100");
- bool override = RNA_boolean_get(op->ptr, "override");
+ bool overwrite = RNA_boolean_get(op->ptr, "overwrite");
bool turnon = true;
if (ed == NULL || !(proxy_25 || proxy_50 || proxy_75 || proxy_100)) {
@@ -3548,7 +3548,7 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
else
seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_100;
- if (!override)
+ if (!overwrite)
seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING;
else
seq->strip->proxy->build_flags &= ~SEQ_PROXY_SKIP_EXISTING;
@@ -3580,7 +3580,7 @@ void SEQUENCER_OT_enable_proxies(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "proxy_50", false, "50%", "");
RNA_def_boolean(ot->srna, "proxy_75", false, "75%", "");
RNA_def_boolean(ot->srna, "proxy_100", false, "100%", "");
- RNA_def_boolean(ot->srna, "override", false, "Override", "");
+ RNA_def_boolean(ot->srna, "overwrite", false, "Overwrite", "");
}
/* change ops */
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index 314b7bf3335..5208013b6fe 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -1903,6 +1903,11 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
}
}
+ /* custom bone may draw outline double-width */
+ if (arm->flag & ARM_POSEMODE) {
+ glLineWidth(1.0f);
+ }
+
/* draw custom bone shapes as wireframes */
if (!(arm->flag & ARM_NO_CUSTOM) &&
(draw_wire || (dt <= OB_WIRE)) )
@@ -1968,11 +1973,6 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
index = -1;
}
}
-
- /* custom bone may draw outline double-width */
- if (arm->flag & ARM_POSEMODE) {
- glLineWidth(1.0f);
- }
/* wire draw over solid only in posemode */
if ((dt <= OB_WIRE) || (arm->flag & ARM_POSEMODE) || ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 884bc6b83ba..73fd77db477 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -7347,7 +7347,7 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_
theme_id = TH_GROUP_ACTIVE;
if (scene->basact != base) {
- theme_shade = -16;
+ theme_shade = -32;
}
}
else {
@@ -8378,9 +8378,13 @@ static void bbs_mesh_solid_verts(Scene *scene, Object *ob)
DM_update_materials(dm, ob);
- dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, GPU_object_material_bind, NULL, me, DM_DRAW_SKIP_HIDDEN);
+ /* Only draw faces to mask out verts, we don't want their selection ID's. */
+ const int G_f_orig = G.f;
+ G.f &= ~G_BACKBUFSEL;
- GPU_object_material_unbind();
+ dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, NULL, NULL, me, DM_DRAW_SKIP_HIDDEN);
+
+ G.f |= (G_f_orig & G_BACKBUFSEL);
bbs_obmode_mesh_verts(ob, dm, 1);
bm_vertoffs = me->totvert + 1;
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 4686ff0523e..ca6e2267218 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -4067,13 +4067,15 @@ static void initTrackball(TransInfo *t)
static void applyTrackballValue(TransInfo *t, const float axis1[3], const float axis2[3], float angles[2])
{
TransData *td = t->data;
- float mat[3][3], smat[3][3], totmat[3][3];
+ float mat[3][3];
+ float axis[3];
+ float angle;
int i;
- axis_angle_normalized_to_mat3(smat, axis1, angles[0]);
- axis_angle_normalized_to_mat3(totmat, axis2, angles[1]);
-
- mul_m3_m3m3(mat, smat, totmat);
+ mul_v3_v3fl(axis, axis1, angles[0]);
+ madd_v3_v3fl(axis, axis2, angles[1]);
+ angle = normalize_v3(axis);
+ axis_angle_normalized_to_mat3(mat, axis, angle);
for (i = 0; i < t->total; i++, td++) {
if (td->flag & TD_NOACTION)
@@ -4083,10 +4085,7 @@ static void applyTrackballValue(TransInfo *t, const float axis1[3], const float
continue;
if (t->flag & T_PROP_EDIT) {
- axis_angle_normalized_to_mat3(smat, axis1, td->factor * angles[0]);
- axis_angle_normalized_to_mat3(totmat, axis2, td->factor * angles[1]);
-
- mul_m3_m3m3(mat, smat, totmat);
+ axis_angle_normalized_to_mat3(mat, axis, td->factor * angle);
}
ElementRotation(t, td, mat, t->around);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index ba474e93b70..4429d19613a 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -771,34 +771,43 @@ int count_set_pose_transflags(int *out_mode, short around, Object *ob)
/* -------- Auto-IK ---------- */
/* adjust pose-channel's auto-ik chainlen */
-static void pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
+static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
{
bConstraint *con;
+ bool changed = false;
/* don't bother to search if no valid constraints */
- if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0)
- return;
+ if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0) {
+ return changed;
+ }
/* check if pchan has ik-constraint */
for (con = pchan->constraints.first; con; con = con->next) {
if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
bKinematicConstraint *data = con->data;
-
+
/* only accept if a temporary one (for auto-ik) */
if (data->flag & CONSTRAINT_IK_TEMP) {
/* chainlen is new chainlen, but is limited by maximum chainlen */
- if ((chainlen == 0) || (chainlen > data->max_rootbone))
+ const int old_rootbone = data->rootbone;
+ if ((chainlen == 0) || (chainlen > data->max_rootbone)) {
data->rootbone = data->max_rootbone;
- else
+ }
+ else {
data->rootbone = chainlen;
+ }
+ changed |= (data->rootbone != old_rootbone);
}
}
}
+
+ return changed;
}
/* change the chain-length of auto-ik */
void transform_autoik_update(TransInfo *t, short mode)
{
+ const short old_len = t->settings->autoik_chainlen;
short *chainlen = &t->settings->autoik_chainlen;
bPoseChannel *pchan;
@@ -812,13 +821,29 @@ void transform_autoik_update(TransInfo *t, short mode)
if (*chainlen > 0) (*chainlen)--;
}
+ /* IK length did not change, skip any updates. */
+ if (old_len == *chainlen) {
+ return;
+ }
+
/* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
if (ELEM(NULL, t->poseobj, t->poseobj->pose))
return;
/* apply to all pose-channels */
+ bool changed = false;
for (pchan = t->poseobj->pose->chanbase.first; pchan; pchan = pchan->next) {
- pchan_autoik_adjust(pchan, *chainlen);
+ changed |= pchan_autoik_adjust(pchan, *chainlen);
+ }
+
+#ifdef WITH_LEGACY_DEPSGRAPH
+ if (!DEG_depsgraph_use_legacy())
+#endif
+ {
+ if (changed) {
+ /* TODO(sergey): Consider doing partial update only. */
+ DAG_relations_tag_update(G.main);
+ }
}
}
@@ -1500,6 +1525,48 @@ static TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struc
return hdata;
}
+/**
+ * For the purpose of transform code we need to behave as if handles are selected,
+ * even when they aren't (see special case below).
+ */
+static int bezt_select_to_transform_triple_flag(
+ const BezTriple *bezt, const bool hide_handles)
+{
+ int flag = 0;
+
+ if (hide_handles) {
+ if (bezt->f2 & SELECT) {
+ flag = (1 << 0) | (1 << 1) | (1 << 2);
+ }
+ }
+ else {
+ flag = (
+ ((bezt->f1 & SELECT) ? (1 << 0) : 0) |
+ ((bezt->f2 & SELECT) ? (1 << 1) : 0) |
+ ((bezt->f3 & SELECT) ? (1 << 2) : 0)
+ );
+ }
+
+ /* Special case for auto & aligned handles:
+ * When a center point is being moved without the handles,
+ * leaving the handles stationary makes no sense and only causes strange behavior,
+ * where one handle is arbitrarily anchored, the other one is aligned and lengthened
+ * based on where the center point is moved. Also a bug when cancelling, see: T52007.
+ *
+ * A more 'correct' solution could be to store handle locations in 'TransDataCurveHandleFlags'.
+ * However that doesn't resolve odd behavior, so best transform the handles in this case.
+ */
+ if ((flag != ((1 << 0) | (1 << 1) | (1 << 2))) && (flag & (1 << 1))) {
+ if (ELEM(bezt->h1, HD_AUTO, HD_ALIGN) &&
+ ELEM(bezt->h2, HD_AUTO, HD_ALIGN))
+ {
+ flag = (1 << 0) | (1 << 1) | (1 << 2);
+ }
+ }
+
+ return flag;
+}
+
static void createTransCurveVerts(TransInfo *t)
{
Curve *cu = t->obedit->data;
@@ -1517,22 +1584,22 @@ static void createTransCurveVerts(TransInfo *t)
/* to be sure */
if (cu->editnurb == NULL) return;
+#define SEL_F1 (1 << 0)
+#define SEL_F2 (1 << 1)
+#define SEL_F3 (1 << 2)
+
/* count total of vertices, check identical as in 2nd loop for making transdata! */
nurbs = BKE_curve_editNurbs_get(cu);
for (nu = nurbs->first; nu; nu = nu->next) {
if (nu->type == CU_BEZIER) {
for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
if (bezt->hide == 0) {
- if (hide_handles) {
- if (bezt->f2 & SELECT) countsel += 3;
- if (is_prop_edit) count += 3;
- }
- else {
- if (bezt->f1 & SELECT) countsel++;
- if (bezt->f2 & SELECT) countsel++;
- if (bezt->f3 & SELECT) countsel++;
- if (is_prop_edit) count += 3;
- }
+ const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
+ if (bezt_tx & SEL_F1) { countsel++; }
+ if (bezt_tx & SEL_F2) { countsel++; }
+ if (bezt_tx & SEL_F3) { countsel++; }
+ if (is_prop_edit) count += 3;
+
}
}
}
@@ -1583,10 +1650,10 @@ static void createTransCurveVerts(TransInfo *t)
}
}
- if (is_prop_edit ||
- ((bezt->f2 & SELECT) && hide_handles) ||
- ((bezt->f1 & SELECT) && hide_handles == 0))
- {
+ /* Elements that will be transform (not always a match to selection). */
+ const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
+
+ if (is_prop_edit || bezt_tx & SEL_F1) {
copy_v3_v3(td->iloc, bezt->vec[0]);
td->loc = bezt->vec[0];
copy_v3_v3(td->center, bezt->vec[(hide_handles ||
@@ -1617,7 +1684,7 @@ static void createTransCurveVerts(TransInfo *t)
}
/* This is the Curve Point, the other two are handles */
- if (is_prop_edit || (bezt->f2 & SELECT)) {
+ if (is_prop_edit || bezt_tx & SEL_F2) {
copy_v3_v3(td->iloc, bezt->vec[1]);
td->loc = bezt->vec[1];
copy_v3_v3(td->center, td->loc);
@@ -1643,7 +1710,7 @@ static void createTransCurveVerts(TransInfo *t)
copy_m3_m3(td->axismtx, axismtx);
}
- if ((bezt->f1 & SELECT) == 0 && (bezt->f3 & SELECT) == 0)
+ if ((bezt_tx & SEL_F1) == 0 && (bezt_tx & SEL_F3) == 0)
/* If the middle is selected but the sides arnt, this is needed */
if (hdata == NULL) { /* if the handle was not saved by the previous handle */
hdata = initTransDataCurveHandles(td, bezt);
@@ -1653,10 +1720,7 @@ static void createTransCurveVerts(TransInfo *t)
count++;
tail++;
}
- if (is_prop_edit ||
- ((bezt->f2 & SELECT) && hide_handles) ||
- ((bezt->f3 & SELECT) && hide_handles == 0))
- {
+ if (is_prop_edit || bezt_tx & SEL_F3) {
copy_v3_v3(td->iloc, bezt->vec[2]);
td->loc = bezt->vec[2];
copy_v3_v3(td->center, bezt->vec[(hide_handles ||
@@ -1711,6 +1775,26 @@ static void createTransCurveVerts(TransInfo *t)
for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
if (bp->hide == 0) {
if (is_prop_edit || (bp->f1 & SELECT)) {
+ float axismtx[3][3];
+
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ if (nu->pntsv == 1) {
+ float normal[3], plane[3];
+
+ BKE_nurb_bpoint_calc_normal(nu, bp, normal);
+ BKE_nurb_bpoint_calc_plane(nu, bp, plane);
+
+ if (createSpaceNormalTangent(axismtx, normal, plane)) {
+ /* pass */
+ }
+ else {
+ normalize_v3(normal);
+ axis_dominant_v3_to_m3(axismtx, normal);
+ invert_m3(axismtx);
+ }
+ }
+ }
+
copy_v3_v3(td->iloc, bp->vec);
td->loc = bp->vec;
copy_v3_v3(td->center, td->loc);
@@ -1729,6 +1813,11 @@ static void createTransCurveVerts(TransInfo *t)
copy_m3_m3(td->smtx, smtx);
copy_m3_m3(td->mtx, mtx);
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ if (nu->pntsv == 1) {
+ copy_m3_m3(td->axismtx, axismtx);
+ }
+ }
td++;
count++;
@@ -1744,6 +1833,10 @@ static void createTransCurveVerts(TransInfo *t)
calc_distanceCurveVerts(head, tail - 1);
}
}
+
+#undef SEL_F1
+#undef SEL_F2
+#undef SEL_F3
}
/* ********************* lattice *************** */
@@ -5349,7 +5442,8 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
}
/* update object's loc/rot to get current rigid body transform */
mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat);
- BKE_object_mat3_to_rot(ob, rot, false);
+ sub_v3_v3(ob->loc, ob->dloc);
+ BKE_object_mat3_to_rot(ob, rot, false); /* drot is already corrected here */
}
}
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 23158495b44..54959304d72 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -817,15 +817,21 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3
else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
Curve *cu = obedit->data;
Nurb *nu = NULL;
- BezTriple *bezt = NULL;
int a;
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- if (activeOnly && BKE_curve_nurb_vert_active_get(cu, &nu, (void *)&bezt)) {
+ void *vert_act = NULL;
+ if (activeOnly && BKE_curve_nurb_vert_active_get(cu, &nu, &vert_act)) {
if (nu->type == CU_BEZIER) {
+ BezTriple *bezt = vert_act;
BKE_nurb_bezt_calc_normal(nu, bezt, normal);
BKE_nurb_bezt_calc_plane(nu, bezt, plane);
}
+ else {
+ BPoint *bp = vert_act;
+ BKE_nurb_bpoint_calc_normal(nu, bp, normal);
+ BKE_nurb_bpoint_calc_plane(nu, bp, plane);
+ }
}
else {
const bool use_handle = (cu->drawflag & CU_HIDE_HANDLES) == 0;
@@ -833,7 +839,7 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3
for (nu = nurbs->first; nu; nu = nu->next) {
/* only bezier has a normal */
if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
+ BezTriple *bezt = nu->bezt;
a = nu->pntsu;
while (a--) {
short flag = 0;
@@ -885,6 +891,36 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3
bezt++;
}
}
+ else if (nu->bp && (nu->pntsv == 1)) {
+ BPoint *bp = nu->bp;
+ a = nu->pntsu;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ float tvec[3];
+
+ BPoint *bp_prev = BKE_nurb_bpoint_get_prev(nu, bp);
+ BPoint *bp_next = BKE_nurb_bpoint_get_next(nu, bp);
+
+ const bool is_prev_sel = bp_prev && (bp_prev->f1 & SELECT);
+ const bool is_next_sel = bp_next && (bp_next->f1 & SELECT);
+ if (is_prev_sel == false && is_next_sel == false) {
+ /* Isolated, add based on surrounding */
+ BKE_nurb_bpoint_calc_normal(nu, bp, tvec);
+ add_v3_v3(normal, tvec);
+ }
+ else if (is_next_sel) {
+ /* A segment, add the edge normal */
+ sub_v3_v3v3(tvec, bp->vec, bp_next->vec );
+ normalize_v3(tvec);
+ add_v3_v3(normal, tvec);
+ }
+
+ BKE_nurb_bpoint_calc_plane(nu, bp, tvec);
+ add_v3_v3(plane, tvec);
+ }
+ bp++;
+ }
+ }
}
}
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index aecd24d4e40..85833f54da6 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -130,18 +130,138 @@ struct SnapObjectContext {
};
-static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt);
+/** \} */
/* -------------------------------------------------------------------- */
-/** \name Support for storing all depths, not just the first (raycast 'all')
+/** Common utilities
+* \{ */
+
+
+#define ITER_SNAP_OBJECTS(use_obedit, ob, obmat, sctx, snap_select, obedit, CODE) \
+ Base *base_act = sctx->scene->basact;\
+ /* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA\
+ * which makes the loop skip it, even the derived mesh will never change\
+ *\
+ * To solve that problem, we do it first as an exception.\
+ * */\
+ if (base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT) {\
+ use_obedit = false;\
+ ob = base_act->object;\
+ obmat = ob->obmat;\
+ CODE\
+ }\
+ for (Base *base = sctx->scene->base.first; base != NULL; base = base->next) {\
+ if ((BASE_VISIBLE_BGMODE(sctx->v3d_data.v3d, sctx->scene, base)) &&\
+ (base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 &&\
+ !((snap_select == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL))) ||\
+ (snap_select == SNAP_NOT_ACTIVE && base == base_act)))\
+ {\
+ Object *obj = base->object;\
+ if (ob->transflag & OB_DUPLI) {\
+ DupliObject *dupli_ob;\
+ ListBase *lb = object_duplilist(sctx->bmain->eval_ctx, sctx->scene, obj);\
+ for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {\
+ use_obedit = obedit && dupli_ob->ob->data == obedit->data;;\
+ ob = use_obedit ? obedit : dupli_ob->ob;\
+ obmat = dupli_ob->mat;\
+ CODE\
+ }\
+ free_object_duplilist(lb);\
+ }\
+ use_obedit = obedit && ob->data == obedit->data;\
+ ob = use_obedit ? obedit : obj;\
+ obmat = ob->obmat;\
+ CODE\
+ }\
+ }\
+
+
+/**
+ * Generates a struct with the immutable parameters that will be used on all objects.
*
- * This uses a list of #SnapObjectHitDepth structs.
+ * \param snap_to: Element to snap, Vertice, Edge or Face.
+ * \param view_proj: ORTHO or PERSP.
+ * Currently only works one at a time, but can eventually operate as flag.
*
- * \{ */
+ * \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_direction: Unit length direction of the ray.
+ * \param depth_range: distances of clipe plane min and clip plane max;
+ */
+static void snap_data_set(
+ SnapData *snapdata,
+ const ARegion *ar, const unsigned short snap_to, const enum eViewProj view_proj,
+ const float mval[2], const float ray_origin[3], const float ray_start[3],
+ const float ray_direction[3], const float depth_range[2])
+{
+ copy_m4_m4(snapdata->pmat, ((RegionView3D *)ar->regiondata)->persmat);
+ snapdata->win_half[0] = ar->winx / 2;
+ snapdata->win_half[1] = ar->winy / 2;
+ copy_v2_v2(snapdata->mval, mval);
+ snapdata->snap_to = snap_to;
+ copy_v3_v3(snapdata->ray_origin, ray_origin);
+ copy_v3_v3(snapdata->ray_start, ray_start);
+ copy_v3_v3(snapdata->ray_dir, ray_direction);
+ snapdata->view_proj = view_proj;
+ copy_v2_v2(snapdata->depth_range, depth_range);
+}
+
+
+MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3])
+{
+ float dvec[3];
+ sub_v3_v3v3(dvec, co, ray_start);
+ return dot_v3v3(dvec, ray_dir);
+}
+
+
+static bool walk_parent_bvhroot_cb(const BVHTreeAxisRange *bounds, void *userdata)
+{
+ BVHTreeRay *ray = userdata;
+ const float bbmin[3] = {bounds[0].min, bounds[1].min, bounds[2].min};
+ const float bbmax[3] = {bounds[0].max, bounds[1].max, bounds[2].max};
+ if (!isect_ray_aabb_v3_simple(ray->origin, ray->direction, bbmin, bbmax, &ray->radius, NULL)) {
+ ray->radius = -1;
+ }
+ return false;
+}
+
+
+static bool isect_ray_bvhroot_v3(struct BVHTree *tree, const float ray_start[3], const float ray_dir[3], float *depth)
+{
+ BVHTreeRay ray;
+ copy_v3_v3(ray.origin, ray_start);
+ copy_v3_v3(ray.direction, ray_dir);
+
+ BLI_bvhtree_walk_dfs(tree, walk_parent_bvhroot_cb, NULL, NULL, &ray);
+
+ if (ray.radius > 0) {
+ *depth = ray.radius;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt);
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Ray Cast Funcs
+* \{ */
+
+/* Store all ray-hits
+ * Support for storing all depths, not just the first (raycast 'all') */
-/* Store all ray-hits */
struct RayCastAll_Data {
void *bvhdata;
@@ -162,6 +282,7 @@ struct RayCastAll_Data {
bool retval;
};
+
static struct SnapObjectHitDepth *hit_depth_create(
const float depth, const float co[3], const float no[3], int index,
Object *ob, const float obmat[4][4], unsigned int ob_uuid)
@@ -229,57 +350,493 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH
}
}
-/** \} */
+static bool raycastDerivedMesh(
+ SnapObjectContext *sctx,
+ const float ray_orig[3], const float ray_start[3], const float ray_dir[3], const float depth_range[2],
+ Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index,
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3], float r_no[3], int *r_index,
+ ListBase *r_hit_list)
+{
+ bool retval = false;
-/* -------------------------------------------------------------------- */
+ if (dm->getNumPolys(dm) == 0) {
+ return retval;
+ }
+
+ float imat[4][4];
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ float ray_start_local[3], ray_normal_local[3];
+ float local_scale, local_depth, len_diff = 0.0f;
+
+ invert_m4_m4(imat, obmat);
+ transpose_m3_m4(timat, imat);
+
+ copy_v3_v3(ray_start_local, ray_start);
+ copy_v3_v3(ray_normal_local, ray_dir);
+
+ mul_m4_v3(imat, ray_start_local);
+ mul_mat3_m4_v3(imat, ray_normal_local);
+
+ /* local scale in normal direction */
+ local_scale = normalize_v3(ray_normal_local);
+ local_depth = *ray_depth;
+ if (local_depth != BVH_RAYCAST_DIST_MAX) {
+ local_depth *= local_scale;
+ }
+
+ /* Test BoundBox */
+ BoundBox *bb = BKE_object_boundbox_get(ob);
+ if (bb) {
+ /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
+ if (!isect_ray_aabb_v3_simple(
+ ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, NULL))
+ {
+ return retval;
+ }
+ }
+
+ SnapObjectData_Mesh *sod = NULL;
+ BVHTreeFromMesh *treedata;
+
+ void **sod_p;
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ sod = *sod_p;
+ }
+ else {
+ sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod->sd.type = SNAP_MESH;
+ }
+
+ if (sod->bvh_trees[2] == NULL) {
+ sod->bvh_trees[2] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
+ }
+
+ treedata = sod->bvh_trees[2];
+
+ if (treedata) {
+ /* the tree is owned by the DM and may have been freed since we last used! */
+ if (treedata->tree) {
+ if (treedata->cached && !bvhcache_has_tree(dm->bvhCache, treedata->tree)) {
+ free_bvhtree_from_mesh(treedata);
+ }
+ else {
+ if (!treedata->vert_allocated) {
+ treedata->vert = DM_get_vert_array(dm, &treedata->vert_allocated);
+ }
+ if (!treedata->loop_allocated) {
+ treedata->loop = DM_get_loop_array(dm, &treedata->loop_allocated);
+ }
+ if (!treedata->looptri_allocated) {
+ if (!sod->poly_allocated) {
+ sod->mpoly = DM_get_poly_array(dm, &sod->poly_allocated);
+ }
+ treedata->looptri = DM_get_looptri_array(
+ dm, treedata->vert,
+ sod->mpoly, dm->getNumPolys(dm),
+ treedata->loop, dm->getNumLoops(dm),
+ &treedata->looptri_allocated);
+ }
+ }
+ }
+
+ if (treedata->tree == NULL) {
+ bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6);
+
+ if (treedata->tree == NULL) {
+ return retval;
+ }
+ }
+ }
+ else {
+ return retval;
+ }
+
+ /* 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 (len_diff == 0.0f) { /* do_ray_start_correction */
+ /* We *need* a reasonably valid len_diff in this case.
+ * Get the distance to bvhtree root */
+ if (!isect_ray_bvhroot_v3(treedata->tree, ray_start_local, ray_normal_local, &len_diff))
+ {
+ return retval;
+ }
+ }
+ /* You need to make sure that ray_start is really far away,
+ * because even in the Orthografic view, in some cases,
+ * the ray can start inside the object (see T50486) */
+ if (len_diff > 400.0f) {
+ float ray_org_local[3];
+
+ copy_v3_v3(ray_org_local, ray_orig);
+ 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_scale);
+ local_depth -= len_diff;
+ }
+ else {
+ len_diff = 0.0f;
+ }
+ if (r_hit_list) {
+ struct RayCastAll_Data data;
+
+ data.bvhdata = treedata;
+ data.raycast_callback = treedata->raycast_callback;
+ data.obmat = obmat;
+ data.timat = timat;
+ data.len_diff = len_diff;
+ data.local_scale = local_scale;
+ data.ob = ob;
+ data.ob_uuid = ob_index;
+ 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);
+
+ retval = data.retval;
+ }
+ else {
+ BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
+
+ if (BLI_bvhtree_ray_cast(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ &hit, treedata->raycast_callback, treedata) != -1)
+ {
+ hit.dist += len_diff;
+ hit.dist /= local_scale;
+ if (hit.dist <= *ray_depth) {
+ *ray_depth = hit.dist;
+ copy_v3_v3(r_loc, hit.co);
+
+ /* back to worldspace */
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ copy_v3_v3(r_no, hit.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+
+ retval = true;
+
+ if (r_index) {
+ *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]);
+ }
+ }
+ }
+ }
+
+ return retval;
+}
+
+static bool raycastEditMesh(
+ SnapObjectContext *sctx,
+ const float ray_orig[3], const float ray_start[3], const float ray_dir[3], const float depth_range[2],
+ Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index,
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3], float r_no[3], int *r_index,
+ ListBase *r_hit_list)
+{
+ bool retval = false;
+ if (em->bm->totface == 0) {
+ return retval;
+ }
+
+ SnapObjectData_EditMesh *sod = NULL;
+
+ BVHTreeFromEditMesh *treedata;
+
+ void **sod_p;
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ sod = *sod_p;
+ }
+ else {
+ sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod->sd.type = SNAP_EDIT_MESH;
+ }
+
+ if (sod->bvh_trees[2] == NULL) {
+ sod->bvh_trees[2] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
+ }
+ treedata = sod->bvh_trees[2];
+
+ if (treedata) {
+ if (treedata->tree == NULL) {
+ BLI_bitmap *elem_mask = NULL;
+ int looptri_num_active = -1;
+
+ if (sctx->callbacks.edit_mesh.test_face_fn) {
+ elem_mask = BLI_BITMAP_NEW(em->tottri, __func__);
+ looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
+ em->bm, elem_mask,
+ sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data);
+ }
+ bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, NULL);
+
+ if (elem_mask) {
+ MEM_freeN(elem_mask);
+ }
+ }
+ if (treedata->tree == NULL) {
+ return retval;
+ }
+ }
+ else {
+ return retval;
+ }
+
+ float imat[4][4];
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ float ray_normal_local[3], ray_start_local[3], len_diff = 0.0f;
+
+ invert_m4_m4(imat, obmat);
+ transpose_m3_m4(timat, imat);
+
+ copy_v3_v3(ray_normal_local, ray_dir);
+ mul_mat3_m4_v3(imat, ray_normal_local);
+
+ copy_v3_v3(ray_start_local, ray_start);
+ mul_m4_v3(imat, ray_start_local);
+
+ /* local scale in normal direction */
+ float local_scale = normalize_v3(ray_normal_local);
+ float local_depth = *ray_depth;
+ if (local_depth != BVH_RAYCAST_DIST_MAX) {
+ local_depth *= local_scale;
+ }
+
+ /* 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 && !((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp) { /* do_ray_start_correction */
+ /* We *need* a reasonably valid len_diff in this case.
+ * Get the distance to bvhtree root */
+ if (!isect_ray_bvhroot_v3(treedata->tree, ray_start_local, ray_normal_local, &len_diff))
+ {
+ return retval;
+ }
+ /* You need to make sure that ray_start is really far away,
+ * because even in the Orthografic view, in some cases,
+ * the ray can start inside the object (see T50486) */
+ if (len_diff > 400.0f) {
+ float ray_org_local[3];
+
+ copy_v3_v3(ray_org_local, ray_orig);
+ 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_scale);
+ local_depth -= len_diff;
+ }
+ else len_diff = 0.0f;
+ }
+ if (r_hit_list) {
+ struct RayCastAll_Data data;
+
+ data.bvhdata = treedata;
+ data.raycast_callback = treedata->raycast_callback;
+ data.obmat = obmat;
+ data.timat = timat;
+ data.len_diff = len_diff;
+ data.local_scale = local_scale;
+ data.ob = ob;
+ data.ob_uuid = ob_index;
+ 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);
+
+ retval = data.retval;
+ }
+ else {
+ BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
+
+ if (BLI_bvhtree_ray_cast(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ &hit, treedata->raycast_callback, treedata) != -1)
+ {
+ hit.dist += len_diff;
+ hit.dist /= local_scale;
+ if (hit.dist <= *ray_depth) {
+ *ray_depth = hit.dist;
+ copy_v3_v3(r_loc, hit.co);
+
+ /* back to worldspace */
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ copy_v3_v3(r_no, hit.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+
+ retval = true;
+
+ if (r_index) {
+ *r_index = hit.index;
+ }
+ }
+ }
+ }
+
+ return retval;
+}
-/** Common utilities
- * \{ */
/**
- * Generates a struct with the immutable parameters that will be used on all objects.
- *
- * \param snap_to: Element to snap, Vertice, Edge or Face.
- * \param view_proj: ORTHO or PERSP.
- * Currently only works one at a time, but can eventually operate as flag.
+ * \param use_obedit: 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_direction: Unit length direction of the ray.
- * \param depth_range: distances of clipe plane min and clip plane max;
+ * \note Duplicate args here are documented at #snapObjectsRay
*/
-static void snap_data_set(
- SnapData *snapdata,
- const ARegion *ar, const unsigned short snap_to, const enum eViewProj view_proj,
- const float mval[2], const float ray_origin[3], const float ray_start[3],
- const float ray_direction[3], const float depth_range[2])
+static bool raycastObj(
+ SnapObjectContext *sctx,
+ const float ray_orig[3], const float ray_start[3], const float ray_dir[3], const float depth_range[2],
+ Object *ob, float obmat[4][4], const unsigned int ob_index,
+ bool use_obedit,
+ /* read/write args */
+ float *ray_depth,
+ /* 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)
{
- if (ar) {
- copy_m4_m4(snapdata->pmat, ((RegionView3D *)ar->regiondata)->persmat);
- snapdata->win_half[0] = ar->winx / 2;
- snapdata->win_half[1] = ar->winy / 2;
+ bool retval = false;
+
+ if (ob->type == OB_MESH) {
+ BMEditMesh *em;
+
+ if (use_obedit) {
+ em = BKE_editmesh_from_object(ob);
+ retval = raycastEditMesh(
+ sctx,
+ ray_orig, ray_start, ray_dir, depth_range,
+ ob, em, obmat, ob_index,
+ ray_depth, r_loc, r_no, r_index, r_hit_list);
+ }
+ else {
+ /* in this case we want the mesh from the editmesh, avoids stale data. see: T45978.
+ * still set the 'em' to NULL, since we only want the 'dm'. */
+ DerivedMesh *dm;
+ em = BKE_editmesh_from_object(ob);
+ if (em) {
+ editbmesh_get_derived_cage_and_final(sctx->scene, ob, em, CD_MASK_BAREMESH, &dm);
+ }
+ else {
+ dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH);
+ }
+ retval = raycastDerivedMesh(
+ sctx,
+ ray_orig, ray_start, ray_dir, depth_range,
+ ob, dm, obmat, ob_index,
+ ray_depth, r_loc, r_no, r_index, r_hit_list);
+
+ dm->release(dm);
+ }
}
- if (mval) {
- copy_v2_v2(snapdata->mval, mval);
+
+ if (retval) {
+ if (r_ob) {
+ *r_ob = ob;
+ copy_m4_m4(r_obmat, obmat);
+ }
}
- snapdata->snap_to = snap_to;
- copy_v3_v3(snapdata->ray_origin, ray_origin);
- copy_v3_v3(snapdata->ray_start, ray_start);
- copy_v3_v3(snapdata->ray_dir, ray_direction);
- snapdata->view_proj = view_proj;
- copy_v2_v2(snapdata->depth_range, depth_range);
+
+ return retval;
}
-MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3])
+
+/**
+ * Main RayCast Function
+ * ======================
+ *
+ * Walks through all objects in the scene to find the `hit` on object surface.
+ *
+ * \param sctx: Snap context to store data.
+ * \param snapdata: struct generated in `set_snapdata`.
+ * \param snap_select : from enum SnapSelect.
+ * \param use_object_edit_cage : Uses the coordinates of BMesh(if any) to do the snapping.
+ * \param obj_list: List with objects to snap (created in `create_object_list`).
+ *
+ * Read/Write Args
+ * ---------------
+ *
+ * \param ray_depth: maximum depth allowed for r_co, elements deeper than this value will be ignored.
+ *
+ * Output Args
+ * -----------
+ *
+ * \param r_loc: Hit location.
+ * \param r_no: Hit normal (optional).
+ * \param r_index: Hit index or -1 when no valid index is found.
+ * (currently only set to the polygon index when when using ``snap_to == SCE_SNAP_MODE_FACE``).
+ * \param r_ob: Hit object.
+ * \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances).
+ * \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
+ *
+ */
+static bool raycastObjects(
+ SnapObjectContext *sctx,
+ const float ray_orig[3], const float ray_start[3], const float ray_dir[3], const float depth_range[2],
+ const SnapSelect snap_select, const bool use_object_edit_cage,
+ /* read/write args */
+ float *ray_depth,
+ /* 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)
{
- float dvec[3];
- sub_v3_v3v3(dvec, co, ray_start);
- return dot_v3v3(dvec, ray_dir);
+ bool retval = false;
+ bool use_obedit;
+
+ unsigned int ob_index = 0;
+
+ Object *ob, *obedit;
+ float (*obmat)[4];
+
+ obedit = use_object_edit_cage ? sctx->scene->obedit : NULL;
+ ITER_SNAP_OBJECTS(use_obedit, ob, obmat, sctx, snap_select, obedit,
+ retval |= raycastObj(
+ sctx,
+ ray_orig, ray_start, ray_dir, depth_range,
+ ob, obmat, ob_index++, use_obedit,
+ ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
+ )
+
+ return retval;
}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** Snap Nearest utilities
+ * \{ */
+
static void copy_dm_vert_no(const int index, float r_no[3], const BVHTreeFromMesh *data)
{
const MVert *vert = data->vert + index;
@@ -558,15 +1115,12 @@ static float dist_squared_to_projected_aabb(
vb2d[0] *= data->win_half[0];
vb2d[1] *= data->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];
+ float dvec[2], edge[2], lambda, rdist;
+ sub_v2_v2v2(dvec, data->mval, va2d);
+ sub_v2_v2v2(edge, vb2d, va2d);
+ lambda = dot_v2v2(dvec, edge);
if (lambda != 0.0f) {
- lambda /= edge[0] * edge[0] + edge[1] * edge[1];
+ lambda /= len_squared_v2(edge);
if (lambda <= 0.0f) {
rdist = len_squared_v2v2(data->mval, va2d);
r_axis_closest[main_axis] = true;
@@ -603,18 +1157,6 @@ static float dist_squared_to_projected_aabb_simple(
return dist_squared_to_projected_aabb(&data, bbmin, bbmax, dummy);
}
-static float dist_aabb_to_plane(
- const float bbmin[3], const float bbmax[3],
- const float plane_co[3], const float plane_no[3])
-{
- const float local_bvmin[3] = {
- (plane_no[0] < 0) ? bbmax[0] : bbmin[0],
- (plane_no[1] < 0) ? bbmax[1] : bbmin[1],
- (plane_no[2] < 0) ? bbmax[2] : bbmin[2],
- };
- return depth_get(local_bvmin, plane_co, plane_no);
-}
-
/** \} */
@@ -1053,21 +1595,15 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
static bool snapDerivedMesh(
SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index,
+ Object *ob, DerivedMesh *dm, float obmat[4][4],
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
- float r_loc[3], float r_no[3], int *r_index,
- ListBase *r_hit_list)
+ float r_loc[3], float r_no[3])
{
bool retval = false;
- if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
- if (dm->getNumPolys(dm) == 0) {
- return retval;
- }
- }
- else if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
+ if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
if (dm->getNumEdges(dm) == 0) {
return retval;
}
@@ -1078,38 +1614,27 @@ static bool snapDerivedMesh(
}
}
- bool need_ray_start_correction_init =
- (snapdata->snap_to == SCE_SNAP_MODE_FACE) &&
- (snapdata->view_proj == VIEW_PROJ_ORTHO);
-
float imat[4][4];
float timat[3][3]; /* transpose inverse matrix for normals */
- float ray_start_local[3], ray_normal_local[3];
- float local_scale, local_depth, len_diff;
+ float ray_normal_local[3];
+ float local_scale;
invert_m4_m4(imat, obmat);
transpose_m3_m4(timat, imat);
- copy_v3_v3(ray_start_local, snapdata->ray_start);
copy_v3_v3(ray_normal_local, snapdata->ray_dir);
- mul_m4_v3(imat, ray_start_local);
mul_mat3_m4_v3(imat, ray_normal_local);
/* local scale in normal direction */
local_scale = normalize_v3(ray_normal_local);
- local_depth = *ray_depth;
- if (local_depth != BVH_RAYCAST_DIST_MAX) {
- local_depth *= local_scale;
- }
float lpmat[4][4];
float ray_org_local[3];
float ray_min_dist;
- if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
- ray_min_dist = snapdata->depth_range[0] * local_scale;
- }
+
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+ ray_min_dist = snapdata->depth_range[0] * local_scale;
copy_v3_v3(ray_org_local, snapdata->ray_origin);
mul_m4_v3(imat, ray_org_local);
@@ -1118,26 +1643,12 @@ static bool snapDerivedMesh(
BoundBox *bb = BKE_object_boundbox_get(ob);
if (bb) {
/* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
- if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
- float dist_px_sq = dist_squared_to_projected_aabb_simple(
- lpmat, snapdata->win_half, ray_min_dist, snapdata->mval,
- ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]);
- if (dist_px_sq > SQUARE(*dist_px)) {
- return retval;
- }
- }
- else {
- /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
- if (!isect_ray_aabb_v3_simple(
- ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL))
- {
- return retval;
- }
+ float dist_px_sq = dist_squared_to_projected_aabb_simple(
+ lpmat, snapdata->win_half, ray_min_dist, snapdata->mval,
+ ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]);
+ if (dist_px_sq > SQUARE(*dist_px)) {
+ return retval;
}
- /* was local_depth, see: T47838 */
- len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local);
- if (len_diff < 0) len_diff = 0.0f;
- need_ray_start_correction_init = false;
}
SnapObjectData_Mesh *sod = NULL;
@@ -1154,9 +1665,6 @@ static bool snapDerivedMesh(
int tree_index = -1;
switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_FACE:
- tree_index = 2;
- break;
case SCE_SNAP_MODE_EDGE:
tree_index = 1;
break;
@@ -1180,179 +1688,71 @@ static bool snapDerivedMesh(
treedata->vert = DM_get_vert_array(dm, &treedata->vert_allocated);
}
if ((tree_index == 1) && !treedata->edge_allocated) {
- treedata->edge = DM_get_edge_array(dm, &treedata->vert_allocated);
- }
- if (tree_index == 2) {
- if (!treedata->loop_allocated) {
- treedata->loop = DM_get_loop_array(dm, &treedata->loop_allocated);
- }
- if (!treedata->looptri_allocated) {
- if (!sod->poly_allocated) {
- sod->mpoly = DM_get_poly_array(dm, &sod->poly_allocated);
- }
- treedata->looptri = DM_get_looptri_array(
- dm, treedata->vert,
- sod->mpoly, dm->getNumPolys(dm),
- treedata->loop, dm->getNumLoops(dm),
- &treedata->looptri_allocated);
- }
+ treedata->edge = DM_get_edge_array(dm, &treedata->edge_allocated);
}
}
}
}
- if (treedata && treedata->tree == NULL) {
- switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_FACE:
- bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6);
- break;
- case SCE_SNAP_MODE_EDGE:
- bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6);
- break;
- case SCE_SNAP_MODE_VERTEX:
- bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6);
- break;
+ if (treedata) {
+ if (treedata->tree == NULL) {
+ switch (snapdata->snap_to) {
+ case SCE_SNAP_MODE_EDGE:
+ bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6);
+ break;
+ case SCE_SNAP_MODE_VERTEX:
+ bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6);
+ break;
+ }
+ }
+ if (treedata->tree == NULL) {
+ return retval;
}
}
- if (!treedata || !treedata->tree) {
+ else {
return retval;
}
- if (snapdata->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 (snapdata->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.
- */
- 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);
- }
- }
- /* You need to make sure that ray_start is really far away,
- * because even in the Orthografic view, in some cases,
- * the ray can start inside the object (see T50486) */
- if (len_diff > 400.0f) {
- /* 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 + snapdata->depth_range[0] * local_scale);
- local_depth -= len_diff;
- }
- else len_diff = 0.0f;
- }
- else {
- len_diff = 0.0f;
- }
- if (r_hit_list) {
- struct RayCastAll_Data data;
-
- data.bvhdata = treedata;
- data.raycast_callback = treedata->raycast_callback;
- data.obmat = obmat;
- data.timat = timat;
- data.len_diff = len_diff;
- data.local_scale = local_scale;
- data.ob = ob;
- data.ob_uuid = ob_index;
- 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);
-
- retval = data.retval;
- }
- else {
- BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
+ /* Warning: the depth_max is currently being used only in perspective view.
+ * It is not correct to limit the maximum depth for elements obtained with nearest
+ * since this limitation depends on the normal and the size of the occlusion face.
+ * And more... ray_depth is being confused with Z-depth here... (varies only the precision) */
+ const float ray_depth_max_global = *ray_depth + snapdata->depth_range[0];
- if (BLI_bvhtree_ray_cast(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- &hit, treedata->raycast_callback, treedata) != -1)
- {
- hit.dist += len_diff;
- hit.dist /= local_scale;
- if (hit.dist <= *ray_depth) {
- *ray_depth = hit.dist;
- copy_v3_v3(r_loc, hit.co);
-
- /* back to worldspace */
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- copy_v3_v3(r_no, hit.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
+ Nearest2dUserData neasrest2d = {
+ .dist_px_sq = SQUARE(*dist_px),
+ .r_axis_closest = {1.0f, 1.0f, 1.0f},
+ .depth_range = {snapdata->depth_range[0], ray_depth_max_global},
+ .userdata = treedata,
+ .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_dm_edge_verts,
+ .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_dm_vert_no,
+ .index = -1};
- retval = true;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest2d.data_precalc, lpmat,
+ snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half,
+ ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local);
- if (r_index) {
- *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]);
- }
- }
- }
- }
- }
- /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */
- else {
+ BVHTree_WalkLeafCallback cb_walk_leaf =
+ (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
+ cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
- /* Warning: the depth_max is currently being used only in perspective view.
- * It is not correct to limit the maximum depth for elements obtained with nearest
- * since this limitation depends on the normal and the size of the occlusion face.
- * And more... ray_depth is being confused with Z-depth here... (varies only the precision) */
- const float ray_depth_max_global = *ray_depth + snapdata->depth_range[0];
-
- Nearest2dUserData neasrest2d = {
- .dist_px_sq = SQUARE(*dist_px),
- .r_axis_closest = {1.0f, 1.0f, 1.0f},
- .depth_range = {snapdata->depth_range[0], ray_depth_max_global},
- .userdata = treedata,
- .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_dm_edge_verts,
- .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_dm_vert_no,
- .index = -1};
-
- dist_squared_to_projected_aabb_precalc(
- &neasrest2d.data_precalc, lpmat,
- snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half,
- ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local);
-
- BVHTree_WalkLeafCallback cb_walk_leaf =
- (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
- cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
-
- BLI_bvhtree_walk_dfs(
- treedata->tree,
- cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
-
- if (neasrest2d.index != -1) {
- copy_v3_v3(r_loc, neasrest2d.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- copy_v3_v3(r_no, neasrest2d.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
- *dist_px = sqrtf(neasrest2d.dist_px_sq);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+ BLI_bvhtree_walk_dfs(
+ treedata->tree,
+ cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
- retval = true;
+ if (neasrest2d.index != -1) {
+ copy_v3_v3(r_loc, neasrest2d.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, neasrest2d.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
}
+ *dist_px = sqrtf(neasrest2d.dist_px_sq);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+
+ retval = true;
}
return retval;
@@ -1360,20 +1760,14 @@ static bool snapDerivedMesh(
static bool snapEditMesh(
SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index,
+ Object *ob, BMEditMesh *em, float obmat[4][4],
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
- float r_loc[3], float r_no[3], int *r_index,
- ListBase *r_hit_list)
+ float r_loc[3], float r_no[3])
{
bool retval = false;
- if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
- if (em->bm->totface == 0) {
- return retval;
- }
- }
if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
if (em->bm->totedge == 0) {
return retval;
@@ -1398,14 +1792,10 @@ static bool snapEditMesh(
/* local scale in normal direction */
float local_scale = normalize_v3(ray_normal_local);
- float local_depth = *ray_depth;
- if (local_depth != BVH_RAYCAST_DIST_MAX) {
- local_depth *= local_scale;
- }
SnapObjectData_EditMesh *sod = NULL;
- BVHTreeFromEditMesh *treedata = NULL;
+ BVHTreeFromEditMesh *treedata;
void **sod_p;
if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
@@ -1418,9 +1808,6 @@ static bool snapEditMesh(
int tree_index = -1;
switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_FACE:
- tree_index = 2;
- break;
case SCE_SNAP_MODE_EDGE:
tree_index = 1;
break;
@@ -1435,197 +1822,90 @@ static bool snapEditMesh(
treedata = sod->bvh_trees[tree_index];
}
- if (treedata && treedata->tree == NULL) {
- BLI_bitmap *elem_mask = NULL;
- switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_FACE:
- {
- int looptri_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_face_fn) {
- elem_mask = BLI_BITMAP_NEW(em->tottri, __func__);
- looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
- em->bm, elem_mask,
- sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data);
+ if (treedata) {
+ if (treedata->tree == NULL) {
+ BLI_bitmap *elem_mask = NULL;
+ switch (snapdata->snap_to) {
+ case SCE_SNAP_MODE_EDGE:
+ {
+ int edges_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_edge_fn) {
+ elem_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
+ edges_num_active = BM_iter_mesh_bitmap_from_filter(
+ BM_EDGES_OF_MESH, em->bm, elem_mask,
+ (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
+ sctx->callbacks.edit_mesh.user_data);
+ }
+ bvhtree_from_editmesh_edges_ex(treedata, em, elem_mask, edges_num_active, 0.0f, 2, 6);
+ break;
}
- bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, NULL);
- break;
- }
- case SCE_SNAP_MODE_EDGE:
- {
- int edges_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_edge_fn) {
- elem_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
- edges_num_active = BM_iter_mesh_bitmap_from_filter(
- BM_EDGES_OF_MESH, em->bm, elem_mask,
- (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
- sctx->callbacks.edit_mesh.user_data);
+ case SCE_SNAP_MODE_VERTEX:
+ {
+ int verts_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_vert_fn) {
+ elem_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
+ verts_num_active = BM_iter_mesh_bitmap_from_filter(
+ BM_VERTS_OF_MESH, em->bm, elem_mask,
+ (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
+ sctx->callbacks.edit_mesh.user_data);
+ }
+ bvhtree_from_editmesh_verts_ex(treedata, em, elem_mask, verts_num_active, 0.0f, 2, 6);
+ break;
}
- bvhtree_from_editmesh_edges_ex(treedata, em, elem_mask, edges_num_active, 0.0f, 2, 6);
- break;
}
- case SCE_SNAP_MODE_VERTEX:
- {
- int verts_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_vert_fn) {
- elem_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
- verts_num_active = BM_iter_mesh_bitmap_from_filter(
- BM_VERTS_OF_MESH, em->bm, elem_mask,
- (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
- sctx->callbacks.edit_mesh.user_data);
- }
- bvhtree_from_editmesh_verts_ex(treedata, em, elem_mask, verts_num_active, 0.0f, 2, 6);
- break;
+ if (elem_mask) {
+ MEM_freeN(elem_mask);
}
}
- if (elem_mask) {
- MEM_freeN(elem_mask);
+ if (treedata->tree == NULL) {
+ return retval;
}
}
-
- if (!treedata || !treedata->tree) {
+ else {
return retval;
}
- if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
- float ray_start_local[3];
- copy_v3_v3(ray_start_local, snapdata->ray_start);
- mul_m4_v3(imat, ray_start_local);
-
- /* 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!
- */
- float len_diff = 0.0f;
- if (snapdata->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.
- */
- 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);
- /* You need to make sure that ray_start is really far away,
- * because even in the Orthografic view, in some cases,
- * the ray can start inside the object (see T50486) */
- if (len_diff > 400.0f) {
- float ray_org_local[3];
-
- copy_v3_v3(ray_org_local, snapdata->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 + snapdata->depth_range[0] * local_scale);
- local_depth -= len_diff;
- }
- else len_diff = 0.0f;
- }
- }
- if (r_hit_list) {
- struct RayCastAll_Data data;
-
- data.bvhdata = treedata;
- data.raycast_callback = treedata->raycast_callback;
- data.obmat = obmat;
- data.timat = timat;
- data.len_diff = len_diff;
- data.local_scale = local_scale;
- data.ob = ob;
- data.ob_uuid = ob_index;
- 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);
-
- retval = data.retval;
- }
- else {
- BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
+ float ray_org_local[3];
+ copy_v3_v3(ray_org_local, snapdata->ray_origin);
+ mul_m4_v3(imat, ray_org_local);
- if (BLI_bvhtree_ray_cast(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- &hit, treedata->raycast_callback, treedata) != -1)
- {
- hit.dist += len_diff;
- hit.dist /= local_scale;
- if (hit.dist <= *ray_depth) {
- *ray_depth = hit.dist;
- copy_v3_v3(r_loc, hit.co);
-
- /* back to worldspace */
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- copy_v3_v3(r_no, hit.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
+ Nearest2dUserData neasrest2d = {
+ .dist_px_sq = SQUARE(*dist_px),
+ .r_axis_closest = {1.0f, 1.0f, 1.0f},
+ .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]},
+ .userdata = treedata,
+ .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_bedge_verts,
+ .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_bvert_no,
+ .index = -1};
- retval = true;
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest2d.data_precalc, lpmat,
+ snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half,
+ (snapdata->depth_range[0] * local_scale), snapdata->mval,
+ ray_org_local, ray_normal_local);
- if (r_index) {
- *r_index = hit.index;
- }
- }
- }
- }
- }
- else {
- float ray_org_local[3];
- copy_v3_v3(ray_org_local, snapdata->ray_origin);
- mul_m4_v3(imat, ray_org_local);
+ BVHTree_WalkLeafCallback cb_walk_leaf =
+ (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
+ cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
- Nearest2dUserData neasrest2d = {
- .dist_px_sq = SQUARE(*dist_px),
- .r_axis_closest = {1.0f, 1.0f, 1.0f},
- .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]},
- .userdata = treedata,
- .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_bedge_verts,
- .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_bvert_no,
- .index = -1};
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
- dist_squared_to_projected_aabb_precalc(
- &neasrest2d.data_precalc, lpmat,
- snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half,
- (snapdata->depth_range[0] * local_scale), snapdata->mval,
- ray_org_local, ray_normal_local);
-
- BVHTree_WalkLeafCallback cb_walk_leaf =
- (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
- cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
-
- BLI_bvhtree_walk_dfs(
- treedata->tree,
- cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
-
- if (neasrest2d.index != -1) {
- copy_v3_v3(r_loc, neasrest2d.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- copy_v3_v3(r_no, neasrest2d.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
- *dist_px = sqrtf(neasrest2d.dist_px_sq);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+ BLI_bvhtree_walk_dfs(
+ treedata->tree,
+ cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
- retval = true;
+ if (neasrest2d.index != -1) {
+ copy_v3_v3(r_loc, neasrest2d.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, neasrest2d.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
}
+ *dist_px = sqrtf(neasrest2d.dist_px_sq);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+
+ retval = true;
}
return retval;
@@ -1638,14 +1918,13 @@ static bool snapEditMesh(
*/
static bool snapObject(
SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, float obmat[4][4], const unsigned int ob_index,
+ Object *ob, float obmat[4][4],
bool use_obedit,
/* read/write args */
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)
+ float r_loc[3], float r_no[3],
+ Object **r_ob, float r_obmat[4][4])
{
bool retval = false;
@@ -1655,10 +1934,9 @@ static bool snapObject(
if (use_obedit) {
em = BKE_editmesh_from_object(ob);
retval = snapEditMesh(
- sctx, snapdata, ob, em, obmat, ob_index,
+ sctx, snapdata, ob, em, obmat,
ray_depth, dist_px,
- r_loc, r_no, r_index,
- r_hit_list);
+ r_loc, r_no);
}
else {
/* in this case we want the mesh from the editmesh, avoids stale data. see: T45978.
@@ -1672,10 +1950,9 @@ static bool snapObject(
dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH);
}
retval = snapDerivedMesh(
- sctx, snapdata, ob, dm, obmat, ob_index,
+ sctx, snapdata, ob, dm, obmat,
ray_depth, dist_px,
- r_loc, r_no,
- r_index, r_hit_list);
+ r_loc, r_no);
dm->release(dm);
}
@@ -1720,6 +1997,7 @@ static bool snapObject(
return retval;
}
+
/**
* Main Snapping Function
* ======================
@@ -1728,8 +2006,8 @@ static bool snapObject(
*
* \param sctx: Snap context to store data.
* \param snapdata: struct generated in `get_snapdata`.
- * \param snap_select: from enum SnapSelect.
- * \param use_object_edit_cage: Uses the coordinates of BMesh (if any) to do the snapping.
+ * \param snap_select : from enum SnapSelect.
+ * \param use_object_edit_cage : Uses the coordinates of BMesh(if any) to do the snapping.
*
* Read/Write Args
* ---------------
@@ -1746,87 +2024,30 @@ static bool snapObject(
* (currently only set to the polygon index when when using ``snap_to == SCE_SNAP_MODE_FACE``).
* \param r_ob: Hit object.
* \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances).
- * \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
*
*/
static bool snapObjectsRay(
SnapObjectContext *sctx, SnapData *snapdata,
- const SnapSelect snap_select,
- const bool use_object_edit_cage,
+ const SnapSelect snap_select, const bool use_object_edit_cage,
/* read/write args */
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)
+ float r_loc[3], float r_no[3],
+ Object **r_ob, float r_obmat[4][4])
{
bool retval = false;
+ bool use_obedit;
- unsigned int ob_index = 0;
- Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL;
-
- /* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA
- * which makes the loop skip it, even the derived mesh will never change
- *
- * To solve that problem, we do it first as an exception.
- * */
- Base *base_act = sctx->scene->basact;
- if (base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT) {
- Object *ob = base_act->object;
+ Object *ob, *obedit;
+ float (*obmat)[4];
+ obedit = use_object_edit_cage ? sctx->scene->obedit : NULL;
+ ITER_SNAP_OBJECTS(use_obedit, ob, obmat, sctx, snap_select, obedit,
retval |= snapObject(
- sctx, snapdata, ob, ob->obmat, ob_index++, false,
+ sctx, snapdata, ob, obmat, use_obedit,
ray_depth, dist_px,
- r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
- }
-
- bool ignore_object_selected = false, ignore_object_active = false;
- switch (snap_select) {
- case SNAP_ALL:
- break;
- case SNAP_NOT_SELECTED:
- ignore_object_selected = true;
- break;
- case SNAP_NOT_ACTIVE:
- ignore_object_active = true;
- break;
- }
- for (Base *base = sctx->scene->base.first; base != NULL; base = base->next) {
- if ((BASE_VISIBLE_BGMODE(sctx->v3d_data.v3d, sctx->scene, base)) &&
- (base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 &&
-
- !((ignore_object_selected && (base->flag & (SELECT | BA_WAS_SEL))) ||
- (ignore_object_active && base == base_act)))
- {
- Object *ob = base->object;
-
- if (ob->transflag & OB_DUPLI) {
- DupliObject *dupli_ob;
- ListBase *lb = object_duplilist(sctx->bmain->eval_ctx, sctx->scene, ob);
-
- for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
- bool use_obedit_dupli = (obedit && dupli_ob->ob->data == obedit->data);
- Object *dupli_snap = (use_obedit_dupli) ? obedit : dupli_ob->ob;
-
- retval |= snapObject(
- sctx, snapdata, dupli_snap, dupli_ob->mat,
- ob_index++, use_obedit_dupli,
- ray_depth, dist_px,
- r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
- }
-
- free_object_duplilist(lb);
- }
-
- bool use_obedit = (obedit != NULL) && (ob->data == obedit->data);
- Object *ob_snap = use_obedit ? obedit : ob;
-
- retval |= snapObject(
- sctx, snapdata, ob_snap, ob->obmat, ob_index++, use_obedit,
- ray_depth, dist_px,
- r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
- }
- }
+ r_loc, r_no, r_ob, r_obmat);
+ )
return retval;
}
@@ -1922,7 +2143,6 @@ void ED_transform_snap_object_context_set_editmesh_callbacks(
bool ED_transform_snap_object_project_ray_ex(
SnapObjectContext *sctx,
- const unsigned short snap_to,
const struct SnapObjectParams *params,
const float ray_start[3], const float ray_normal[3],
float *ray_depth,
@@ -1931,16 +2151,11 @@ bool ED_transform_snap_object_project_ray_ex(
{
const float depth_range[2] = {0.0f, FLT_MAX};
- SnapData snapdata;
- snap_data_set(
- &snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE,
- NULL, ray_start, ray_start, ray_normal, depth_range);
-
- return snapObjectsRay(
- sctx, &snapdata,
+ return raycastObjects(
+ sctx,
+ ray_start, ray_start, ray_normal, depth_range,
params->snap_select, params->use_object_edit_cage,
- ray_depth, NULL,
- r_loc, r_no, r_index, r_ob, r_obmat, NULL);
+ ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, NULL);
}
/**
@@ -1952,7 +2167,6 @@ bool ED_transform_snap_object_project_ray_ex(
*/
bool ED_transform_snap_object_project_ray_all(
SnapObjectContext *sctx,
- const unsigned short snap_to,
const struct SnapObjectParams *params,
const float ray_start[3], const float ray_normal[3],
float ray_depth, bool sort,
@@ -1967,15 +2181,11 @@ bool ED_transform_snap_object_project_ray_all(
float ray_depth_prev = ray_depth;
#endif
- SnapData snapdata;
- snap_data_set(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL,
- ray_start, ray_start, ray_normal, depth_range);
-
- bool retval = snapObjectsRay(
- sctx, &snapdata,
+ bool retval = raycastObjects(
+ sctx,
+ ray_start, ray_start, ray_normal, depth_range,
params->snap_select, params->use_object_edit_cage,
- &ray_depth, NULL,
- NULL, NULL, NULL, NULL, NULL,
+ &ray_depth, NULL, NULL, NULL, NULL, NULL,
r_hit_list);
/* meant to be readonly for 'all' hits, ensure it is */
@@ -2008,7 +2218,6 @@ static bool transform_snap_context_project_ray_impl(
/* try snap edge, then face if it fails */
ret = ED_transform_snap_object_project_ray_ex(
sctx,
- SCE_SNAP_MODE_FACE,
params,
ray_start, ray_normal, ray_depth,
r_co, r_no, NULL,
@@ -2154,16 +2363,24 @@ bool ED_transform_snap_object_project_view3d_ex(
ray_depth = &ray_depth_fallback;
}
- SnapData snapdata;
- const enum eViewProj view_proj = ((RegionView3D *)ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
- snap_data_set(&snapdata, ar, snap_to, view_proj, mval,
- ray_origin, ray_start, ray_normal, depth_range);
+ if (snap_to == SCE_SNAP_MODE_FACE) {
+ return raycastObjects(
+ sctx,
+ ray_origin, ray_start, ray_normal, depth_range,
+ params->snap_select, params->use_object_edit_cage,
+ ray_depth, r_loc, r_no, r_index, NULL, NULL, NULL);
+ }
+ else {
+ SnapData snapdata;
+ const enum eViewProj view_proj = ((RegionView3D *)ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
+ snap_data_set(&snapdata, ar, snap_to, view_proj, mval,
+ ray_origin, ray_start, ray_normal, depth_range);
- return snapObjectsRay(
- sctx, &snapdata,
- params->snap_select, params->use_object_edit_cage,
- ray_depth, dist_px,
- r_loc, r_no, r_index, NULL, NULL, NULL);
+ return snapObjectsRay(
+ sctx, &snapdata,
+ params->snap_select, params->use_object_edit_cage,
+ ray_depth, dist_px, r_loc, r_no, NULL, NULL);
+ }
}
bool ED_transform_snap_object_project_view3d(
@@ -2204,7 +2421,6 @@ bool ED_transform_snap_object_project_all_view3d_ex(
return ED_transform_snap_object_project_ray_all(
sctx,
- SCE_SNAP_MODE_FACE,
params,
ray_start, ray_normal, ray_depth, sort,
r_hit_list);
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index 4e021d4833e..419c15bf83f 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -334,6 +334,12 @@ static int ed_undo_redo_exec(bContext *C, wmOperator *UNUSED(op))
return ret ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
+static int ed_undo_redo_poll(bContext *C)
+{
+ wmOperator *last_op = WM_operator_last_redo(C);
+ return last_op && ED_operator_screenactive(C) &&
+ WM_operator_check_ui_enabled(C, last_op->type->name);
+}
/* ********************** */
@@ -385,7 +391,7 @@ void ED_OT_undo_redo(wmOperatorType *ot)
/* api callbacks */
ot->exec = ed_undo_redo_exec;
- ot->poll = ED_operator_screenactive;
+ ot->poll = ed_undo_redo_poll;
}
/* ui callbacks should call this rather than calling WM_operator_repeat() themselves */
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 7334ce882e1..5125bb54dd4 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -1162,8 +1162,13 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo
BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */
- /* use winding so we don't consider overlapping islands as connected, see T44320 */
- vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, true);
+ /* Note, we had 'use winding' so we don't consider overlapping islands as connected, see T44320
+ * this made *every* projection split the island into front/back islands.
+ * Keep 'use_winding' to false, see: T50970.
+ *
+ * Better solve this by having a delimit option for select-linked operator,
+ * keeping island-select working as is. */
+ vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, false);
if (vmap == NULL)
return;