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/animation/anim_filter.c2
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c2
-rw-r--r--source/blender/editors/include/ED_image.h26
-rw-r--r--source/blender/editors/include/ED_transform.h1
-rw-r--r--source/blender/editors/mesh/editface.c7
-rw-r--r--source/blender/editors/mesh/editmesh_knife_project.c5
-rw-r--r--source/blender/editors/object/object_add.c75
-rw-r--r--source/blender/editors/object/object_constraint.c136
-rw-r--r--source/blender/editors/physics/particle_edit.c3
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c2
-rw-r--r--source/blender/editors/space_file/filelist.c13
-rw-r--r--source/blender/editors/space_file/fsmenu.c22
-rw-r--r--source/blender/editors/space_image/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_image/image_buttons.c2
-rw-r--r--source/blender/editors/space_image/image_ops.c274
-rw-r--r--source/blender/editors/space_image/image_sequence.c249
-rw-r--r--source/blender/editors/space_info/info_stats.c5
-rw-r--r--source/blender/editors/space_nla/space_nla.c8
-rw-r--r--source/blender/editors/space_view3d/drawobject.c9
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c8
-rw-r--r--source/blender/editors/transform/transform.c4
-rw-r--r--source/blender/editors/transform/transform_convert.c26
-rw-r--r--source/blender/editors/transform/transform_convert.h4
-rw-r--r--source/blender/editors/transform/transform_convert_action.c11
-rw-r--r--source/blender/editors/transform/transform_convert_graph.c11
-rw-r--r--source/blender/editors/transform/transform_convert_nla.c11
-rw-r--r--source/blender/editors/transform/transform_convert_sequencer.c24
-rw-r--r--source/blender/editors/transform/transform_generics.c26
-rw-r--r--source/blender/editors/transform/transform_ops.c10
-rw-r--r--source/blender/editors/transform/transform_snap_object.c303
-rw-r--r--source/blender/editors/util/ed_util.c13
33 files changed, 646 insertions, 655 deletions
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index a9ddc53e5bb..5a0e60f8d58 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -2996,7 +2996,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_m
*/
if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
/* layer visibility - we check both object and base, since these may not be in sync yet */
- if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
+ if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0 || (base->flag & BASE_VISIBLE_VIEWLAYER) == 0) {
return false;
}
diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
index 5ff76d886c2..4490892695f 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
@@ -91,7 +91,7 @@ static bool gizmo_calc_rect_view_scale(const wmGizmo *gz, const float dims[2], f
static bool gizmo_calc_rect_view_margin(const wmGizmo *gz, const float dims[2], float margin[2])
{
float handle_size;
- handle_size = 0.15f;
+ handle_size = 10.0f;
handle_size *= gz->scale_final;
float scale_xy[2];
if (!gizmo_calc_rect_view_scale(gz, dims, scale_xy)) {
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index e6d8684a8b2..d78c2620253 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -24,15 +24,21 @@
#ifndef __ED_IMAGE_H__
#define __ED_IMAGE_H__
+#include "DNA_listBase.h"
+#include "DNA_space_types.h"
+
struct ARegion;
struct ImBuf;
struct Image;
struct ImageUser;
+struct LinkNodePair;
+struct Main;
struct ReportList;
struct Scene;
struct SpaceImage;
struct ViewLayer;
struct bContext;
+struct wmOperator;
struct wmWindowManager;
/* image_edit.c, exported for transform */
@@ -116,4 +122,24 @@ bool ED_image_should_save_modified(const struct bContext *C);
int ED_image_save_all_modified_info(const struct bContext *C, struct ReportList *reports);
bool ED_image_save_all_modified(const struct bContext *C, struct ReportList *reports);
+/* image_sequence.c */
+typedef struct ImageFrameRange {
+ struct ImageFrameRange *next, *prev;
+
+ /** Absolute file path of the first file in the range. */
+ char filepath[FILE_MAX];
+ /* Sequence parameters. */
+ int length;
+ int offset;
+ /* UDIM tiles. */
+ ListBase udim_tiles;
+
+ /* Temporary data. */
+ ListBase frames;
+} ImageFrameRange;
+
+ListBase ED_image_filesel_detect_sequences(struct Main *bmain,
+ struct wmOperator *op,
+ const bool detect_udim);
+
#endif /* __ED_IMAGE_H__ */
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index c66967a9365..d53ad7c4229 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -153,7 +153,6 @@ int BIF_countTransformOrientation(const struct bContext *C);
#define P_GPENCIL_EDIT (1 << 13)
#define P_CURSOR_EDIT (1 << 14)
#define P_CLNOR_INVALIDATE (1 << 15)
-#define P_MOUSE (1 << 16)
void Transform_Properties(struct wmOperatorType *ot, int flags);
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 5c9fb866df7..5f948595a22 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -35,6 +35,7 @@
#include "BKE_customdata.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
+#include "BKE_object.h"
#include "ED_mesh.h"
#include "ED_screen.h"
@@ -80,8 +81,8 @@ void paintface_flush_flags(struct bContext *C, Object *ob, short flag)
return;
}
- Mesh *me_orig = ob_eval->runtime.mesh_orig;
- Mesh *me_eval = ob_eval->runtime.mesh_eval;
+ Mesh *me_orig = (Mesh *)ob_eval->runtime.data_orig;
+ Mesh *me_eval = (Mesh *)ob_eval->runtime.data_eval;
bool updated = false;
if (me_orig != NULL && me_eval != NULL && me_orig->totpoly == me->totpoly) {
@@ -443,7 +444,7 @@ bool paintface_mouse_select(
void paintvert_flush_flags(Object *ob)
{
Mesh *me = BKE_mesh_from_object(ob);
- Mesh *me_eval = ob->runtime.mesh_eval;
+ Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
MVert *mvert_eval, *mv;
const int *index_array = NULL;
int totvert;
diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c
index 8d5c1469694..21de89d33dd 100644
--- a/source/blender/editors/mesh/editmesh_knife_project.c
+++ b/source/blender/editors/mesh/editmesh_knife_project.c
@@ -33,6 +33,7 @@
#include "BKE_curve.h"
#include "BKE_editmesh.h"
#include "BKE_mesh_runtime.h"
+#include "BKE_object.h"
#include "BKE_report.h"
#include "DEG_depsgraph.h"
@@ -61,9 +62,9 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C,
struct Mesh *me_eval;
bool me_eval_needs_free;
- if (ob->type == OB_MESH || ob->runtime.mesh_eval) {
+ if (ob->type == OB_MESH || ob->runtime.data_eval) {
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- me_eval = ob_eval->runtime.mesh_eval;
+ me_eval = BKE_object_get_evaluated_mesh(ob_eval);
if (me_eval == NULL) {
Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 7891f59a62e..a8eaa663285 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -410,45 +410,54 @@ bool ED_object_add_generic_get_opts(bContext *C,
rot = _rot;
}
- prop = RNA_struct_find_property(op->ptr, "align");
- int alignment = RNA_property_enum_get(op->ptr, prop);
- bool alignment_set = RNA_property_is_set(op->ptr, prop);
-
if (RNA_struct_property_is_set(op->ptr, "rotation")) {
+ /* If rotation is set, always use it. Alignment (and corresponding user preference)
+ * can be ignored since this is in world space anyways.
+ * To not confuse (e.g. on redo), dont set it to ALIGN_WORLD in the op UI though. */
*is_view_aligned = false;
- RNA_property_enum_set(op->ptr, prop, ALIGN_WORLD);
- alignment = ALIGN_WORLD;
- }
- else if (alignment_set) {
- *is_view_aligned = alignment == ALIGN_VIEW;
+ RNA_float_get_array(op->ptr, "rotation", rot);
}
else {
- *is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0;
- if (*is_view_aligned) {
- RNA_property_enum_set(op->ptr, prop, ALIGN_VIEW);
- alignment = ALIGN_VIEW;
+ int alignment = ALIGN_WORLD;
+ prop = RNA_struct_find_property(op->ptr, "align");
+
+ if (RNA_property_is_set(op->ptr, prop)) {
+ /* If alignment is set, always use it. */
+ *is_view_aligned = alignment == ALIGN_VIEW;
+ alignment = RNA_property_enum_get(op->ptr, prop);
}
- else if (U.flag & USER_ADD_CURSORALIGNED) {
- RNA_property_enum_set(op->ptr, prop, ALIGN_CURSOR);
- alignment = ALIGN_CURSOR;
+ else {
+ /* If alignment is not set, use User Preferences. */
+ *is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0;
+ if (*is_view_aligned) {
+ RNA_property_enum_set(op->ptr, prop, ALIGN_VIEW);
+ alignment = ALIGN_VIEW;
+ }
+ else if ((U.flag & USER_ADD_CURSORALIGNED) != 0) {
+ RNA_property_enum_set(op->ptr, prop, ALIGN_CURSOR);
+ alignment = ALIGN_CURSOR;
+ }
+ else {
+ RNA_property_enum_set(op->ptr, prop, ALIGN_WORLD);
+ alignment = ALIGN_WORLD;
+ }
}
- }
-
- switch (alignment) {
- case ALIGN_WORLD:
- RNA_float_get_array(op->ptr, "rotation", rot);
- break;
- case ALIGN_VIEW:
- ED_object_rotation_from_view(C, rot, view_align_axis);
- RNA_float_set_array(op->ptr, "rotation", rot);
- break;
- case ALIGN_CURSOR: {
- const Scene *scene = CTX_data_scene(C);
- float tmat[3][3];
- BKE_scene_cursor_rot_to_mat3(&scene->cursor, tmat);
- mat3_normalized_to_eul(rot, tmat);
- RNA_float_set_array(op->ptr, "rotation", rot);
- break;
+ switch (alignment) {
+ case ALIGN_WORLD:
+ RNA_float_get_array(op->ptr, "rotation", rot);
+ break;
+ case ALIGN_VIEW:
+ ED_object_rotation_from_view(C, rot, view_align_axis);
+ RNA_float_set_array(op->ptr, "rotation", rot);
+ break;
+ case ALIGN_CURSOR: {
+ const Scene *scene = CTX_data_scene(C);
+ float tmat[3][3];
+ BKE_scene_cursor_rot_to_mat3(&scene->cursor, tmat);
+ mat3_normalized_to_eul(rot, tmat);
+ RNA_float_set_array(op->ptr, "rotation", rot);
+ break;
+ }
}
}
}
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 906a9e44870..bfff36bb83a 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -871,118 +871,31 @@ void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot)
/* ------------- Child-Of Constraint ------------------ */
-static void child_get_inverse_matrix_owner_bone(
- Depsgraph *depsgraph, wmOperator *op, Scene *scene, Object *ob, float invmat[4][4])
+/* Force evaluation so that the 'set inverse' flag is handled.
+ * No-op when the constraint is enabled, as in such cases the evaluation will happen anyway.
+ */
+static void force_evaluation_if_constraint_disabled(bContext *C, Object *ob, bConstraint *con)
{
- /* For bone owner we want to do this in evaluated domain.
- * BKE_pose_where_is / BKE_pose_where_is_bone relies on (re)evaluating parts of the scene
- * and copying new evaluated stuff back to original.
- */
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- bConstraint *con_eval = edit_constraint_property_get(op, ob_eval, CONSTRAINT_TYPE_CHILDOF);
-
- /* nullify inverse matrix first */
- unit_m4(invmat);
-
- bPoseChannel *pchan_eval = BKE_pose_channel_active(ob_eval);
-
- /* try to find a pose channel - assume that this is the constraint owner */
- /* TODO: get from context instead? */
- if (ob_eval && ob_eval->pose && pchan_eval) {
- bConstraint *con_last;
-
- /* calculate/set inverse matrix:
- * We just calculate all transform-stack eval up to but not including this constraint.
- * This is because inverse should just inverse correct for just the constraint's influence
- * when it gets applied; that is, at the time of application, we don't know anything about
- * what follows.
- */
- float imat[4][4], tmat[4][4];
- float pmat[4][4];
-
- /* make sure we passed the correct constraint */
- BLI_assert(BLI_findindex(&pchan_eval->constraints, con_eval) != -1);
-
- /* 1. calculate posemat where inverse doesn't exist yet (inverse was cleared above),
- * to use as baseline ("pmat") to derive delta from. This extra calc saves users
- * from having pressing "Clear Inverse" first
- */
- BKE_pose_where_is(depsgraph, scene, ob_eval);
- copy_m4_m4(pmat, pchan_eval->pose_mat);
-
- /* 2. knock out constraints starting from this one */
- con_last = pchan_eval->constraints.last;
- pchan_eval->constraints.last = con_eval->prev;
-
- if (con_eval->prev) {
- /* new end must not point to this one, else this chain cutting is useless */
- con_eval->prev->next = NULL;
- }
- else {
- /* constraint was first */
- pchan_eval->constraints.first = NULL;
- }
-
- /* 3. solve pose without disabled constraints */
- BKE_pose_where_is(depsgraph, scene, ob_eval);
-
- /* 4. determine effect of constraint by removing the newly calculated
- * pchan->pose_mat from the original pchan->pose_mat, thus determining
- * the effect of the constraint
- */
- invert_m4_m4(imat, pchan_eval->pose_mat);
- mul_m4_m4m4(tmat, pmat, imat);
- invert_m4_m4(invmat, tmat);
-
- /* 5. restore constraints */
- pchan_eval->constraints.last = con_last;
-
- if (con_eval->prev) {
- /* hook up prev to this one again */
- con_eval->prev->next = con_eval;
- }
- else {
- /* set as first again */
- pchan_eval->constraints.first = con_eval;
- }
-
- /* 6. recalculate pose with new inv-mat applied */
- /* this one is unnecessary? (DEG seems to update correctly without)
- + if we leave this in, we have to click "Set Inverse" twice to see updates...
- BKE_pose_where_is(depsgraph, scene, ob_eval); */
+ if ((con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) == 0) {
+ return;
}
-}
-
-static void child_get_inverse_matrix_owner_object(
- Depsgraph *depsgraph, Scene *scene, Object *ob, bConstraint *con, float invmat[4][4])
-{
- /* nullify inverse matrix first */
- unit_m4(invmat);
-
- if (ob) {
- Object workob;
-
- /* make sure we passed the correct constraint */
- BLI_assert(BLI_findindex(&ob->constraints, con) != -1);
- UNUSED_VARS_NDEBUG(con);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
- /* use BKE_object_workob_calc_parent to find inverse - just like for normal parenting */
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(invmat, workob.obmat);
- }
+ short flag_backup = con->flag;
+ con->flag &= ~(CONSTRAINT_DISABLE | CONSTRAINT_OFF);
+ BKE_object_eval_constraints(depsgraph, scene, ob);
+ con->flag = flag_backup;
}
/* ChildOf Constraint - set inverse callback */
static int childof_set_inverse_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL;
- const int owner = RNA_enum_get(op->ptr, "owner");
/* despite 3 layers of checks, we may still not be able to find a constraint */
if (data == NULL) {
@@ -991,12 +904,11 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
- child_get_inverse_matrix_owner_object(depsgraph, scene, ob, con, data->invmat);
- }
- else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
- child_get_inverse_matrix_owner_bone(depsgraph, op, scene, ob, data->invmat);
- }
+ /* Set a flag to request recalculation on next update. */
+ data->flag |= CHILDOF_SET_INVERSE;
+
+ /* Force constraint to run, it will perform the recalculation. */
+ force_evaluation_if_constraint_disabled(C, ob, con);
ED_object_constraint_update(bmain, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
@@ -1231,12 +1143,9 @@ void CONSTRAINT_OT_followpath_path_animate(wmOperatorType *ot)
static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL;
- const int owner = RNA_enum_get(op->ptr, "owner");
/* despite 3 layers of checks, we may still not be able to find a constraint */
if (data == NULL) {
@@ -1246,12 +1155,11 @@ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
- child_get_inverse_matrix_owner_object(depsgraph, scene, ob, con, data->invmat);
- }
- else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
- child_get_inverse_matrix_owner_bone(depsgraph, op, scene, ob, data->invmat);
- }
+ /* Set a flag to request recalculation on next update. */
+ data->flag |= OBJECTSOLVER_SET_INVERSE;
+
+ /* Force constraint to run, it will perform the recalculation. */
+ force_evaluation_if_constraint_disabled(C, ob, con);
ED_object_constraint_update(bmain, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 92e76ab31fa..49b6acc9003 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -488,7 +488,8 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
static bool PE_create_shape_tree(PEData *data, Object *shapeob)
{
- Mesh *mesh = BKE_object_get_evaluated_mesh(data->depsgraph, shapeob);
+ Object *shapeob_eval = DEG_get_evaluated_object(data->depsgraph, shapeob);
+ Mesh *mesh = BKE_object_get_evaluated_mesh(shapeob_eval);
memset(&data->shape_bvh, 0, sizeof(data->shape_bvh));
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 8c8fc412663..e58183bfc0f 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -1062,7 +1062,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
keymap->poll = weight_paint_mode_poll;
/*Weight paint's Vertex Selection Mode */
- keymap = WM_keymap_ensure(keyconf, "Weight Paint Vertex Selection", 0, 0);
+ keymap = WM_keymap_ensure(keyconf, "Paint Vertex Selection (Weight, Vertex)", 0, 0);
keymap->poll = vert_paint_poll;
/* Image/Texture Paint mode */
@@ -1070,7 +1070,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
keymap->poll = image_texture_paint_poll;
/* face-mask mode */
- keymap = WM_keymap_ensure(keyconf, "Face Mask", 0, 0);
+ keymap = WM_keymap_ensure(keyconf, "Paint Face Mask (Weight, Vertex, Texture)", 0, 0);
keymap->poll = facemask_paint_poll;
/* paint stroke */
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 7372ea6d44a..6971182e5b8 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -181,7 +181,7 @@ static MDeformVert *defweight_prev_init(MDeformVert *dvert_prev,
* (without evaluating modifiers) */
static bool vertex_paint_use_fast_update_check(Object *ob)
{
- Mesh *me_eval = ob->runtime.mesh_eval;
+ Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
if (me_eval != NULL) {
Mesh *me = BKE_mesh_from_object(ob);
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 28e6d95beb3..9defff74c6f 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -2181,8 +2181,17 @@ int ED_path_extension_type(const char *path)
else if (BLI_path_extension_check(path, ".py")) {
return FILE_TYPE_PYSCRIPT;
}
- else if (BLI_path_extension_check_n(
- path, ".txt", ".glsl", ".osl", ".data", ".pov", ".ini", ".mcr", ".inc", NULL)) {
+ else if (BLI_path_extension_check_n(path,
+ ".txt",
+ ".glsl",
+ ".osl",
+ ".data",
+ ".pov",
+ ".ini",
+ ".mcr",
+ ".inc",
+ ".fountain",
+ NULL)) {
return FILE_TYPE_TEXT;
}
else if (BLI_path_extension_check_n(path, ".ttf", ".ttc", ".pfb", ".otf", ".otc", NULL)) {
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index 94747e79c84..dcd348706d6 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -115,8 +115,9 @@ struct FSMenuEntry *ED_fsmenu_get_category(struct FSMenu *fsmenu, FSMenuCategory
*/
static GHash *fsmenu_xdg_user_dirs_parse(const char *home)
{
- size_t data_len;
- char *data;
+ /* Add to the default for variable, equals & quotes. */
+ char l[128 + FILE_MAXDIR];
+ FILE *fp;
/* Check if the config file exists. */
{
@@ -128,17 +129,14 @@ static GHash *fsmenu_xdg_user_dirs_parse(const char *home)
else {
BLI_path_join(filepath, sizeof(filepath), home, ".config", "user-dirs.dirs", NULL);
}
- data = BLI_file_read_text_as_mem_with_newline_as_nil(filepath, true, 1, &data_len);
- if (data == NULL) {
+ fp = BLI_fopen(filepath, "r");
+ if (!fp) {
return NULL;
}
}
/* By default there are 8 paths. */
GHash *xdg_map = BLI_ghash_str_new_ex(__func__, 8);
- char *data_end = data + data_len;
- uint l_len;
- for (char *l = data; l != data_end; l += l_len + 1) {
- l_len = strlen(l);
+ while (fgets(l, sizeof(l), fp) != NULL) { /* read a line */
/* Avoid inserting invalid values. */
if (STRPREFIX(l, "XDG_")) {
@@ -146,9 +144,12 @@ static GHash *fsmenu_xdg_user_dirs_parse(const char *home)
if (l_value != NULL) {
*l_value = '\0';
l_value++;
- if (*l_value == '"' && l[l_len - 1] == '"') {
+
+ BLI_str_rstrip(l_value);
+ const uint l_value_len = strlen(l_value);
+ if ((l_value[0] == '"') && (l_value_len > 0) && (l_value[l_value_len - 1] == '"')) {
l_value++;
- l[l_len - 1] = '\0';
+ l_value[l_value_len - 1] = '\0';
char l_value_expanded[FILE_MAX];
char *l_value_final = l_value;
@@ -166,7 +167,6 @@ static GHash *fsmenu_xdg_user_dirs_parse(const char *home)
}
}
}
- MEM_freeN(data);
return xdg_map;
}
diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt
index 5abcff436f1..12de74c6ae7 100644
--- a/source/blender/editors/space_image/CMakeLists.txt
+++ b/source/blender/editors/space_image/CMakeLists.txt
@@ -43,6 +43,7 @@ set(SRC
image_draw.c
image_edit.c
image_ops.c
+ image_sequence.c
image_undo.c
space_image.c
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index f4688ce17fd..54bd2f37f3a 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -985,7 +985,7 @@ void uiTemplateImage(uiLayout *layout,
void *lock;
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
- if (ibuf->rect_float && (ibuf->flags & IB_halffloat) == 0) {
+ if (ibuf && ibuf->rect_float && (ibuf->flags & IB_halffloat) == 0) {
uiItemR(col, &imaptr, "use_half_precision", 0, NULL, ICON_NONE);
}
BKE_image_release_ibuf(ima, ibuf, lock);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index a3fa03b18b7..fe1cb1ead9e 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1207,18 +1207,6 @@ typedef struct ImageOpenData {
ImageFormatData im_format;
} ImageOpenData;
-typedef struct ImageFrameRange {
- struct ImageFrameRange *next, *prev;
- ListBase frames;
- /** The full path of the first file in the list of image files */
- char filepath[FILE_MAX];
-} ImageFrameRange;
-
-typedef struct ImageFrame {
- struct ImageFrame *next, *prev;
- int framenr;
-} ImageFrame;
-
static void image_open_init(bContext *C, wmOperator *op)
{
ImageOpenData *iod;
@@ -1233,179 +1221,18 @@ static void image_open_cancel(bContext *UNUSED(C), wmOperator *op)
op->customdata = NULL;
}
-/**
- * Get a list of frames from the list of image files matching the first file name sequence pattern.
- * \param ptr[in]: The RNA pointer containing the "directory" entry and "files" collection.
- * \param frames_all[out]: the list of frame numbers found in the files matching
- * the first one by name.
- */
-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);
- RNA_BEGIN (ptr, itemptr, "files") {
- char base_head[FILE_MAX], base_tail[FILE_MAX];
- char head[FILE_MAX], tail[FILE_MAX];
- unsigned short digits;
- char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
- ImageFrame *frame = MEM_callocN(sizeof(ImageFrame), "image_frame");
-
- /* use the first file in the list as base filename */
- frame->framenr = BLI_stringdec(filename, head, tail, &digits);
-
- /* still in the same sequence */
- if (do_frame_range && (frame_range != NULL) && (STREQLEN(base_head, head, FILE_MAX)) &&
- (STREQLEN(base_tail, tail, FILE_MAX))) {
- /* pass */
- }
- else {
- /* 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);
-
- 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;
-}
-
-static int image_cmp_frame(const void *a, const void *b)
-{
- const ImageFrame *frame_a = a;
- const ImageFrame *frame_b = b;
-
- if (frame_a->framenr < frame_b->framenr) {
- return -1;
- }
- if (frame_a->framenr > frame_b->framenr) {
- return 1;
- }
- return 0;
-}
-
-/* Checks whether the given filepath refers to a UDIM texture.
- * If yes, the range from 1001 to the highest tile is returned, otherwise 0.
- *
- * If the result is positive, the filepath will be overwritten with that of
- * the 1001 tile.
- * udim_tiles may get filled even if the result ultimately is false! */
-static int image_get_udim(char *filepath, LinkNodePair *udim_tiles)
-{
- char filename[FILE_MAX], dirname[FILE_MAXDIR];
- BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename));
-
- unsigned short digits;
- char base_head[FILE_MAX], base_tail[FILE_MAX];
- int id = BLI_stringdec(filename, base_head, base_tail, &digits);
-
- if (id < 1001 || id >= IMA_UDIM_MAX) {
- return 0;
- }
-
- bool is_udim = true;
- bool has_primary = false;
- int max_udim = 0;
-
- struct direntry *dir;
- uint totfile = BLI_filelist_dir_contents(dirname, &dir);
- for (int i = 0; i < totfile; i++) {
- if (!(dir[i].type & S_IFREG)) {
- continue;
- }
- char head[FILE_MAX], tail[FILE_MAX];
- id = BLI_stringdec(dir[i].relname, head, tail, &digits);
-
- if (digits > 4 || !(STREQLEN(base_head, head, FILE_MAX)) ||
- !(STREQLEN(base_tail, tail, FILE_MAX))) {
- continue;
- }
-
- if (id < 1001 || id >= IMA_UDIM_MAX) {
- is_udim = false;
- break;
- }
- if (id == 1001) {
- has_primary = true;
- }
-
- BLI_linklist_append(udim_tiles, POINTER_FROM_INT(id));
- max_udim = max_ii(max_udim, id);
- }
- BLI_filelist_free(dir, totfile);
-
- if (is_udim && has_primary) {
- char primary_filename[FILE_MAX];
- BLI_stringenc(primary_filename, base_head, base_tail, digits, 1001);
- BLI_join_dirfile(filepath, FILE_MAX, dirname, primary_filename);
- return max_udim - 1000;
- }
- return 0;
-}
-
-/**
- * Return the start (offset) and the length of the sequence of
- * continuous frames in the list of frames.
- *
- * \param frames: [in] the list of frame numbers, as a side-effect the list is sorted.
- * \param ofs: [out] offset the first frame number in the sequence.
- * \return the number of contiguous frames in the sequence
- */
-static int image_sequence_get_len(ImageFrameRange *frame_range,
- int *ofs,
- char *filepath_range,
- LinkNodePair *udim_tiles)
-{
- ImageFrame *frame;
-
- BLI_listbase_sort(&frame_range->frames, image_cmp_frame);
- BLI_strncpy(filepath_range, frame_range->filepath, FILE_MAX);
-
- frame = frame_range->frames.first;
- if (frame != NULL) {
- int frame_curr = frame->framenr;
- (*ofs) = frame_curr;
-
- if (udim_tiles != NULL) {
- int len_udim = image_get_udim(filepath_range, udim_tiles);
- if (len_udim > 0) {
- *ofs = 1001;
- return len_udim;
- }
- }
-
- while (frame != NULL && (frame->framenr == frame_curr)) {
- frame_curr++;
- frame = frame->next;
- }
- return frame_curr - (*ofs);
- }
- *ofs = 0;
- return 0;
-}
-
static Image *image_open_single(Main *bmain,
wmOperator *op,
- const char *filepath,
+ ImageFrameRange *range,
const char *relbase,
bool is_relative_path,
- bool use_multiview,
- int frame_seq_len,
- int frame_seq_ofs,
- LinkNodePair *udim_tiles)
+ bool use_multiview)
{
bool exists = false;
Image *ima = NULL;
errno = 0;
- ima = BKE_image_load_exists_ex(bmain, filepath, &exists);
+ ima = BKE_image_load_exists_ex(bmain, range->filepath, &exists);
if (!ima) {
if (op->customdata) {
@@ -1414,7 +1241,7 @@ static Image *image_open_single(Main *bmain,
BKE_reportf(op->reports,
RPT_ERROR,
"Cannot read '%s': %s",
- filepath,
+ range->filepath,
errno ? strerror(errno) : TIP_("unsupported image format"));
return NULL;
}
@@ -1439,11 +1266,11 @@ static Image *image_open_single(Main *bmain,
BKE_image_free_views(ima);
}
- if ((frame_seq_len > 1) && (ima->source == IMA_SRC_FILE)) {
- if (udim_tiles && frame_seq_ofs == 1001) {
+ if ((range->length > 1) && (ima->source == IMA_SRC_FILE)) {
+ if (range->udim_tiles.first && range->offset == 1001) {
ima->source = IMA_SRC_TILED;
- for (LinkNode *node = udim_tiles->list; node; node = node->next) {
- BKE_image_add_tile(ima, POINTER_AS_INT(node->link), NULL);
+ for (LinkData *node = range->udim_tiles.first; node; node = node->next) {
+ BKE_image_add_tile(ima, POINTER_AS_INT(node->data), NULL);
}
}
else {
@@ -1464,7 +1291,6 @@ static int image_open_exec(bContext *C, wmOperator *op)
ImageUser *iuser = NULL;
ImageOpenData *iod = op->customdata;
Image *ima = NULL;
- char filepath[FILE_MAX];
int frame_seq_len = 0;
int frame_ofs = 1;
@@ -1476,83 +1302,21 @@ static int image_open_exec(bContext *C, wmOperator *op)
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")) {
- bool was_relative = BLI_path_is_rel(filepath);
- ListBase frame_ranges_all;
-
- 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;
-
- LinkNodePair udim_tiles = {NULL};
- LinkNodePair *udim_tiles_ptr = use_udim ? (&udim_tiles) : NULL;
-
- char filepath_range[FILE_MAX];
- int frame_range_seq_len = image_sequence_get_len(
- frame_range, &frame_range_ofs, filepath_range, udim_tiles_ptr);
- BLI_freelistN(&frame_range->frames);
-
- if (was_relative) {
- BLI_path_rel(filepath_range, BKE_main_blendfile_path(bmain));
- }
-
- Image *ima_range = image_open_single(bmain,
- op,
- filepath_range,
- BKE_main_blendfile_path(bmain),
- is_relative_path,
- use_multiview,
- frame_range_seq_len,
- frame_range_ofs,
- udim_tiles_ptr);
-
- /* take the first image */
- if ((ima == NULL) && ima_range) {
- ima = ima_range;
- frame_seq_len = frame_range_seq_len;
- frame_ofs = frame_range_ofs;
- }
+ ListBase ranges = ED_image_filesel_detect_sequences(bmain, op, use_udim);
+ for (ImageFrameRange *range = ranges.first; range; range = range->next) {
+ Image *ima_range = image_open_single(
+ bmain, op, range, BKE_main_blendfile_path(bmain), is_relative_path, use_multiview);
- BLI_linklist_free(udim_tiles.list, NULL);
+ /* take the first image */
+ if ((ima == NULL) && ima_range) {
+ ima = ima_range;
+ frame_seq_len = range->length;
+ frame_ofs = range->offset;
}
- BLI_freelistN(&frame_ranges_all);
- }
- else {
- /* for drag & drop etc. */
-
- LinkNodePair udim_tiles = {NULL};
- frame_seq_len = 1;
- char filepath_range[FILE_MAX];
- BLI_strncpy(filepath_range, filepath, FILE_MAX);
-
- if (use_udim > 0) {
- /* Try to find UDIM tiles corresponding to the image */
- int udim_len = image_get_udim(filepath_range, &udim_tiles);
-
- /* If we found something, mark the image as tiled. */
- if (udim_len) {
- frame_seq_len = udim_len;
- frame_ofs = 1001;
- }
- }
-
- ima = image_open_single(bmain,
- op,
- filepath_range,
- BKE_main_blendfile_path(bmain),
- is_relative_path,
- use_multiview,
- frame_seq_len,
- frame_ofs,
- &udim_tiles);
- BLI_linklist_free(udim_tiles.list, NULL);
+ BLI_freelistN(&range->udim_tiles);
}
+ BLI_freelistN(&ranges);
if (ima == NULL) {
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/space_image/image_sequence.c b/source/blender/editors/space_image/image_sequence.c
new file mode 100644
index 00000000000..09e717621d8
--- /dev/null
+++ b/source/blender/editors/space_image/image_sequence.c
@@ -0,0 +1,249 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup spimage
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_fileops.h"
+#include "BLI_fileops_types.h"
+#include "BLI_linklist.h"
+#include "BLI_listbase.h"
+#include "BLI_math_base.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_image_types.h"
+#include "DNA_space_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_access.h"
+
+#include "BKE_image.h"
+#include "BKE_main.h"
+
+#include "ED_image.h"
+
+#include "WM_types.h"
+
+typedef struct ImageFrame {
+ struct ImageFrame *next, *prev;
+ int framenr;
+} ImageFrame;
+
+/**
+ * Get a list of frames from the list of image files matching the first file
+ * name sequence pattern. The files and directory are read from standard
+ * fileselect operator properties.
+ *
+ * The output is a list of frame ranges, each containg a list of frames with
+ * matching names.
+ */
+static void image_sequence_get_frame_ranges(wmOperator *op, ListBase *ranges)
+{
+ char dir[FILE_MAXDIR];
+ const bool do_frame_range = RNA_boolean_get(op->ptr, "use_sequence_detection");
+ ImageFrameRange *range = NULL;
+
+ RNA_string_get(op->ptr, "directory", dir);
+ RNA_BEGIN (op->ptr, itemptr, "files") {
+ char base_head[FILE_MAX], base_tail[FILE_MAX];
+ char head[FILE_MAX], tail[FILE_MAX];
+ unsigned short digits;
+ char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ ImageFrame *frame = MEM_callocN(sizeof(ImageFrame), "image_frame");
+
+ /* use the first file in the list as base filename */
+ frame->framenr = BLI_stringdec(filename, head, tail, &digits);
+
+ /* still in the same sequence */
+ if (do_frame_range && (range != NULL) && (STREQLEN(base_head, head, FILE_MAX)) &&
+ (STREQLEN(base_tail, tail, FILE_MAX))) {
+ /* pass */
+ }
+ else {
+ /* start a new frame range */
+ range = MEM_callocN(sizeof(*range), __func__);
+ BLI_join_dirfile(range->filepath, sizeof(range->filepath), dir, filename);
+ BLI_addtail(ranges, range);
+
+ BLI_strncpy(base_head, head, sizeof(base_head));
+ BLI_strncpy(base_tail, tail, sizeof(base_tail));
+ }
+
+ BLI_addtail(&range->frames, frame);
+ MEM_freeN(filename);
+ }
+ RNA_END;
+}
+
+static int image_cmp_frame(const void *a, const void *b)
+{
+ const ImageFrame *frame_a = a;
+ const ImageFrame *frame_b = b;
+
+ if (frame_a->framenr < frame_b->framenr) {
+ return -1;
+ }
+ if (frame_a->framenr > frame_b->framenr) {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Checks whether the given filepath refers to a UDIM texture.
+ * If yes, the range from 1001 to the highest tile is returned, otherwise 0.
+ *
+ * If the result is positive, the filepath will be overwritten with that of
+ * the 1001 tile.
+ *
+ * udim_tiles may get filled even if the result ultimately is false!
+ */
+static int image_get_udim(char *filepath, ListBase *udim_tiles)
+{
+ char filename[FILE_MAX], dirname[FILE_MAXDIR];
+ BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename));
+
+ unsigned short digits;
+ char base_head[FILE_MAX], base_tail[FILE_MAX];
+ int id = BLI_stringdec(filename, base_head, base_tail, &digits);
+
+ if (id < 1001 || id >= IMA_UDIM_MAX) {
+ return 0;
+ }
+
+ bool is_udim = true;
+ bool has_primary = false;
+ int max_udim = 0;
+
+ struct direntry *dir;
+ uint totfile = BLI_filelist_dir_contents(dirname, &dir);
+ for (int i = 0; i < totfile; i++) {
+ if (!(dir[i].type & S_IFREG)) {
+ continue;
+ }
+ char head[FILE_MAX], tail[FILE_MAX];
+ id = BLI_stringdec(dir[i].relname, head, tail, &digits);
+
+ if (digits > 4 || !(STREQLEN(base_head, head, FILE_MAX)) ||
+ !(STREQLEN(base_tail, tail, FILE_MAX))) {
+ continue;
+ }
+
+ if (id < 1001 || id >= IMA_UDIM_MAX) {
+ is_udim = false;
+ break;
+ }
+ if (id == 1001) {
+ has_primary = true;
+ }
+
+ BLI_addtail(udim_tiles, BLI_genericNodeN(POINTER_FROM_INT(id)));
+ max_udim = max_ii(max_udim, id);
+ }
+ BLI_filelist_free(dir, totfile);
+
+ if (is_udim && has_primary) {
+ char primary_filename[FILE_MAX];
+ BLI_stringenc(primary_filename, base_head, base_tail, digits, 1001);
+ BLI_join_dirfile(filepath, FILE_MAX, dirname, primary_filename);
+ return max_udim - 1000;
+ }
+ return 0;
+}
+
+/**
+ * From a list of frames, compute the start (offset) and length of the sequence
+ * of contiguous frames. If UDIM is detect, it will return UDIM tiles as well.
+ */
+static void image_detect_frame_range(ImageFrameRange *range, const bool detect_udim)
+{
+ /* UDIM */
+ if (detect_udim) {
+ int len_udim = image_get_udim(range->filepath, &range->udim_tiles);
+
+ if (len_udim > 0) {
+ range->offset = 1001;
+ range->length = len_udim;
+ return;
+ }
+ }
+
+ /* Image Sequence */
+ BLI_listbase_sort(&range->frames, image_cmp_frame);
+
+ ImageFrame *frame = range->frames.first;
+ if (frame != NULL) {
+ int frame_curr = frame->framenr;
+ range->offset = frame_curr;
+
+ while (frame != NULL && (frame->framenr == frame_curr)) {
+ frame_curr++;
+ frame = frame->next;
+ }
+
+ range->length = frame_curr - range->offset;
+ }
+ else {
+ range->length = 1;
+ range->offset = 0;
+ }
+}
+
+/* Used for both images and volume file loading. */
+ListBase ED_image_filesel_detect_sequences(Main *bmain, wmOperator *op, const bool detect_udim)
+{
+ ListBase ranges;
+ BLI_listbase_clear(&ranges);
+
+ char filepath[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filepath);
+
+ /* File browser. */
+ if (RNA_struct_property_is_set(op->ptr, "directory") &&
+ RNA_struct_property_is_set(op->ptr, "files")) {
+ const bool was_relative = BLI_path_is_rel(filepath);
+
+ image_sequence_get_frame_ranges(op, &ranges);
+ for (ImageFrameRange *range = ranges.first; range; range = range->next) {
+ image_detect_frame_range(range, detect_udim);
+ BLI_freelistN(&range->frames);
+
+ if (was_relative) {
+ BLI_path_rel(range->filepath, BKE_main_blendfile_path(bmain));
+ }
+ }
+ }
+ /* Filepath property for drag & drop etc. */
+ else {
+ ImageFrameRange *range = MEM_callocN(sizeof(*range), __func__);
+ BLI_addtail(&ranges, range);
+
+ BLI_strncpy(range->filepath, filepath, FILE_MAX);
+ image_detect_frame_range(range, detect_udim);
+ }
+
+ return ranges;
+}
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 225ca72a7d0..d00083d343b 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -137,7 +137,7 @@ static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset)
switch (ob->type) {
case OB_MESH: {
/* we assume evaluated mesh is already built, this strictly does stats now. */
- Mesh *me_eval = ob->runtime.mesh_eval;
+ Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
if (!BLI_gset_add(objects_gset, me_eval)) {
break;
}
@@ -153,8 +153,7 @@ static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset)
case OB_SURF:
case OB_CURVE:
case OB_FONT: {
- Mesh *me_eval = ob->runtime.mesh_eval;
-
+ Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
if ((me_eval != NULL) && !BLI_gset_add(objects_gset, me_eval)) {
break;
}
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index 5cd2a86adf8..e5f6b25ee25 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -340,6 +340,8 @@ static void nla_region_listener(wmWindow *UNUSED(win),
case ND_OB_ACTIVE:
case ND_FRAME:
case ND_MARKERS:
+ case ND_LAYER_CONTENT:
+ case ND_OB_SELECT:
ED_region_tag_redraw(ar);
break;
}
@@ -349,6 +351,7 @@ static void nla_region_listener(wmWindow *UNUSED(win),
case ND_BONE_ACTIVE:
case ND_BONE_SELECT:
case ND_KEYS:
+ case ND_DRAW:
ED_region_tag_redraw(ar);
break;
}
@@ -379,6 +382,8 @@ static void nla_main_region_listener(wmWindow *UNUSED(win),
case ND_FRAME:
case ND_FRAME_RANGE:
case ND_MARKERS:
+ case ND_LAYER_CONTENT:
+ case ND_OB_SELECT:
ED_region_tag_redraw(ar);
break;
}
@@ -474,6 +479,8 @@ static void nla_channel_region_listener(wmWindow *UNUSED(win),
case NC_SCENE:
switch (wmn->data) {
case ND_OB_ACTIVE:
+ case ND_LAYER_CONTENT:
+ case ND_OB_SELECT:
ED_region_tag_redraw(ar);
break;
}
@@ -483,6 +490,7 @@ static void nla_channel_region_listener(wmWindow *UNUSED(win),
case ND_BONE_ACTIVE:
case ND_BONE_SELECT:
case ND_KEYS:
+ case ND_DRAW:
ED_region_tag_redraw(ar);
break;
}
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 0daa5aa53ae..00f61a4d0aa 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -28,9 +28,9 @@
#include "BLI_math.h"
#include "BKE_DerivedMesh.h"
-#include "BKE_global.h"
-
#include "BKE_editmesh.h"
+#include "BKE_global.h"
+#include "BKE_object.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -120,8 +120,9 @@ void ED_draw_object_facemap(Depsgraph *depsgraph,
Mesh *me = ob->data;
{
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- if (ob_eval->runtime.mesh_eval) {
- me = ob_eval->runtime.mesh_eval;
+ Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
+ if (me_eval != NULL) {
+ me = me_eval;
}
}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 9d84309d222..df743415fec 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -361,10 +361,10 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar)
/* object ops. */
/* important to be before Pose keymap since they can both be enabled at once */
- keymap = WM_keymap_ensure(wm->defaultconf, "Face Mask", 0, 0);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Paint Face Mask (Weight, Vertex, Texture)", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
- keymap = WM_keymap_ensure(wm->defaultconf, "Weight Paint Vertex Selection", 0, 0);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Paint Vertex Selection (Weight, Vertex)", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
/* Before 'Pose' so weight paint menus aren't overridden by pose menus. */
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 06a4147e34d..4ff8a9a3884 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -98,7 +98,7 @@
#include "view3d_intern.h" /* own include */
-#define M_GOLDEN_RATION_CONJUGATE 0.618033988749895f
+#define M_GOLDEN_RATIO_CONJUGATE 0.618033988749895f
/* -------------------------------------------------------------------- */
/** \name General Functions
@@ -452,7 +452,7 @@ static void drawviewborder_triangle(
if (w > h) {
if (golden) {
- ofs = w * (1.0f - (1.0f / M_GOLDEN_RATION_CONJUGATE));
+ ofs = w * (1.0f - M_GOLDEN_RATIO_CONJUGATE);
}
else {
ofs = h * (h / w);
@@ -472,7 +472,7 @@ static void drawviewborder_triangle(
}
else {
if (golden) {
- ofs = h * (1.0f - (1.0f / M_GOLDEN_RATION_CONJUGATE));
+ ofs = h * (1.0f - M_GOLDEN_RATIO_CONJUGATE);
}
else {
ofs = w * (w / h);
@@ -662,7 +662,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View
}
if (ca->dtx & CAM_DTX_GOLDEN) {
- drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f - (1.0f / M_GOLDEN_RATION_CONJUGATE));
+ drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f - M_GOLDEN_RATIO_CONJUGATE);
}
if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) {
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index bc81817647e..ed42a0e35f3 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1635,9 +1635,9 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
}
- if ((prop = RNA_struct_find_property(op->ptr, "mouse_coordinate_override"))) {
+ if ((prop = RNA_struct_find_property(op->ptr, "center_override"))) {
/* Important for redo operations. */
- RNA_property_int_set_array(op->ptr, prop, t->mouse.imval);
+ RNA_property_float_set_array(op->ptr, prop, t->center_global);
}
if (t->flag & T_PROP_EDIT_ALL) {
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 027ae04795a..c2e3c8ef508 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -69,6 +69,8 @@
#include "ED_clip.h"
#include "ED_mask.h"
+#include "UI_view2d.h"
+
#include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */
#include "WM_types.h"
@@ -787,6 +789,28 @@ void clipUVData(TransInfo *t)
/* ********************* ANIMATION EDITORS (GENERAL) ************************* */
+/**
+ * For modal operation: `t->center_global` may not have been set yet.
+ */
+void transform_convert_center_global_v2(TransInfo *t, float r_center[2])
+{
+ if (t->flag & T_MODAL) {
+ UI_view2d_region_to_view(
+ (View2D *)t->view, t->mouse.imval[0], t->mouse.imval[1], &r_center[0], &r_center[1]);
+ }
+ else {
+ copy_v2_v2(r_center, t->center_global);
+ }
+}
+
+void transform_convert_center_global_v2_int(TransInfo *t, int r_center[2])
+{
+ float center[2];
+ transform_convert_center_global_v2(t, center);
+ r_center[0] = round_fl_to_int(center[0]);
+ r_center[1] = round_fl_to_int(center[1]);
+}
+
/* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
bool FrameOnMouseSide(char side, float frame, float cframe)
{
@@ -2514,7 +2538,7 @@ void createTransData(bContext *C, TransInfo *t)
t->obedit_type = -1;
t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point trasnform */
- createTransSeqData(C, t);
+ createTransSeqData(t);
countAndCleanTransDataContainer(t);
}
else if (t->spacetype == SPACE_GRAPH) {
diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h
index 075bf0a5a4b..d616f24ba86 100644
--- a/source/blender/editors/transform/transform_convert.h
+++ b/source/blender/editors/transform/transform_convert.h
@@ -104,6 +104,8 @@ void transform_around_single_fallback(TransInfo *t);
bool constraints_list_needinv(TransInfo *t, ListBase *list);
void calc_distanceCurveVerts(TransData *head, TransData *tail);
struct TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTriple *bezt);
+void transform_convert_center_global_v2(TransInfo *t, float r_center[2]);
+void transform_convert_center_global_v2_int(TransInfo *t, int r_center[2]);
bool FrameOnMouseSide(char side, float frame, float cframe);
/* transform_convert_action.c */
@@ -162,7 +164,7 @@ void createTransParticleVerts(bContext *C, TransInfo *t);
void createTransSculpt(TransInfo *t);
/* transform_convert_sequence.c */
-void createTransSeqData(bContext *C, TransInfo *t);
+void createTransSeqData(TransInfo *t);
/* transform_convert_tracking.c */
void createTransTrackingData(bContext *C, TransInfo *t);
diff --git a/source/blender/editors/transform/transform_convert_action.c b/source/blender/editors/transform/transform_convert_action.c
index 0b1d2757435..42e8523d4cb 100644
--- a/source/blender/editors/transform/transform_convert_action.c
+++ b/source/blender/editors/transform/transform_convert_action.c
@@ -36,8 +36,6 @@
#include "ED_anim_api.h"
-#include "UI_view2d.h"
-
#include "transform.h"
#include "transform_convert.h"
@@ -333,11 +331,10 @@ void createTransActionData(bContext *C, TransInfo *t)
/* which side of the current frame should be allowed */
if (t->mode == TFM_TIME_EXTEND) {
- /* only side on which mouse is gets transformed */
- float xmouse, ymouse;
-
- UI_view2d_region_to_view(&ac.ar->v2d, t->mouse.imval[0], t->mouse.imval[1], &xmouse, &ymouse);
- t->frame_side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side
+ /* only side on which center is gets transformed */
+ float center[2];
+ transform_convert_center_global_v2(t, center);
+ t->frame_side = (center[0] > CFRA) ? 'R' : 'L';
}
else {
/* normal transform - both sides of current frame are considered */
diff --git a/source/blender/editors/transform/transform_convert_graph.c b/source/blender/editors/transform/transform_convert_graph.c
index f6f982e854a..502679efedf 100644
--- a/source/blender/editors/transform/transform_convert_graph.c
+++ b/source/blender/editors/transform/transform_convert_graph.c
@@ -1,4 +1,4 @@
-/*
+/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -261,11 +261,10 @@ void createTransGraphEditData(bContext *C, TransInfo *t)
/* which side of the current frame should be allowed */
// XXX we still want this mode, but how to get this using standard transform too?
if (t->mode == TFM_TIME_EXTEND) {
- /* only side on which mouse is gets transformed */
- float xmouse, ymouse;
-
- UI_view2d_region_to_view(v2d, t->mouse.imval[0], t->mouse.imval[1], &xmouse, &ymouse);
- t->frame_side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side
+ /* only side on which center is gets transformed */
+ float center[2];
+ transform_convert_center_global_v2(t, center);
+ t->frame_side = (center[0] > CFRA) ? 'R' : 'L';
}
else {
/* normal transform - both sides of current frame are considered */
diff --git a/source/blender/editors/transform/transform_convert_nla.c b/source/blender/editors/transform/transform_convert_nla.c
index 114968ec83f..7c34c583210 100644
--- a/source/blender/editors/transform/transform_convert_nla.c
+++ b/source/blender/editors/transform/transform_convert_nla.c
@@ -35,8 +35,6 @@
#include "ED_anim_api.h"
-#include "UI_view2d.h"
-
#include "transform.h"
#include "transform_convert.h"
@@ -73,11 +71,10 @@ void createTransNlaData(bContext *C, TransInfo *t)
/* which side of the current frame should be allowed */
if (t->mode == TFM_TIME_EXTEND) {
- /* only side on which mouse is gets transformed */
- float xmouse, ymouse;
-
- UI_view2d_region_to_view(&ac.ar->v2d, t->mouse.imval[0], t->mouse.imval[1], &xmouse, &ymouse);
- t->frame_side = (xmouse > CFRA) ? 'R' : 'L';
+ /* only side on which center is gets transformed */
+ float center[2];
+ transform_convert_center_global_v2(t, center);
+ t->frame_side = (center[0] > CFRA) ? 'R' : 'L';
}
else {
/* normal transform - both sides of current frame are considered */
diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c
index 4baf0e8a3cb..a35c814ee23 100644
--- a/source/blender/editors/transform/transform_convert_sequencer.c
+++ b/source/blender/editors/transform/transform_convert_sequencer.c
@@ -31,8 +31,6 @@
#include "BKE_sequencer.h"
#include "BKE_report.h"
-#include "UI_view2d.h"
-
#include "transform.h"
#include "transform_convert.h"
@@ -522,18 +520,16 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
DEG_id_tag_update(&t->scene->id, ID_RECALC_SEQUENCER_STRIPS);
}
-void createTransSeqData(bContext *C, TransInfo *t)
+void createTransSeqData(TransInfo *t)
{
#define XXX_DURIAN_ANIM_TX_HACK
- View2D *v2d = UI_view2d_fromcontext(C);
Scene *scene = t->scene;
Editing *ed = BKE_sequencer_editing_get(t->scene, false);
TransData *td = NULL;
TransData2D *td2d = NULL;
TransDataSeq *tdsq = NULL;
TransSeq *ts = NULL;
- int xmouse;
int count = 0;
@@ -545,18 +541,10 @@ void createTransSeqData(bContext *C, TransInfo *t)
}
tc->custom.type.free_cb = freeSeqData;
-
- xmouse = (int)UI_view2d_region_to_view_x(v2d, t->mouse.imval[0]);
-
- /* which side of the current frame should be allowed */
- if (t->mode == TFM_TIME_EXTEND) {
- /* only side on which mouse is gets transformed */
- t->frame_side = (xmouse > CFRA) ? 'R' : 'L';
- }
- else {
- /* normal transform - both sides of current frame are considered */
- t->frame_side = 'B';
- }
+ /* only side on which center is gets transformed */
+ int center[2];
+ transform_convert_center_global_v2_int(t, center);
+ t->frame_side = (center[0] > CFRA) ? 'R' : 'L';
#ifdef XXX_DURIAN_ANIM_TX_HACK
{
@@ -599,7 +587,7 @@ void createTransSeqData(bContext *C, TransInfo *t)
SeqTransDataBounds(t, ed->seqbasep, ts);
/* set the snap mode based on how close the mouse is at the end/start points */
- if (abs(xmouse - ts->max) > abs(xmouse - ts->min)) {
+ if (abs(center[0] - ts->max) > abs(center[0] - ts->min)) {
ts->snap_left = true;
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index c925f5c9a8e..7d9a122f802 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1374,17 +1374,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
bGPdata *gpd = CTX_data_gpencil_data(C);
PropertyRNA *prop;
- if (op && (prop = RNA_struct_find_property(op->ptr, "mouse_coordinate_override")) &&
- RNA_property_is_set(op->ptr, prop)) {
- RNA_property_int_get_array(op->ptr, prop, t->mval);
- }
- else if (event) {
- copy_v2_v2_int(t->mval, event->mval);
- }
- else {
- zero_v2_int(t->mval);
- }
-
t->depsgraph = CTX_data_depsgraph_pointer(C);
t->scene = sce;
t->view_layer = view_layer;
@@ -1413,11 +1402,16 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->redraw = TREDRAW_HARD; /* redraw first time */
- t->mouse.imval[0] = t->mval[0];
- t->mouse.imval[1] = t->mval[1];
-
- t->con.imval[0] = t->mouse.imval[0];
- t->con.imval[1] = t->mouse.imval[1];
+ int mval[2];
+ if (event) {
+ copy_v2_v2_int(mval, event->mval);
+ }
+ else {
+ zero_v2_int(mval);
+ }
+ copy_v2_v2_int(t->mval, mval);
+ copy_v2_v2_int(t->mouse.imval, mval);
+ copy_v2_v2_int(t->con.imval, mval);
t->transform = NULL;
t->handleEvent = NULL;
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index d3d5d785eac..39f6f24eb8d 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -694,14 +694,6 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
RNA_def_property_ui_text(prop, "Center Override", "Force using this center value (when set)");
}
- if (flags & P_MOUSE) {
- prop = RNA_def_property(ot->srna, "mouse_coordinate_override", PROP_INT, PROP_XYZ);
- RNA_def_property_array(prop, 2);
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- RNA_def_property_ui_text(
- prop, "Mouse Coordinate Override", "Force using this mouse value (when set)");
- }
-
if ((flags & P_NO_DEFAULTS) == 0) {
prop = RNA_def_boolean(ot->srna,
"release_confirm",
@@ -1247,7 +1239,7 @@ static void TRANSFORM_OT_transform(struct wmOperatorType *ot)
Transform_Properties(ot,
P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR |
- P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER | P_MOUSE);
+ P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
static int transform_from_gizmo_invoke(bContext *C,
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index c4358168adb..ecd267d6f2a 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -19,9 +19,6 @@
*/
#include <stdlib.h>
-#include <math.h>
-#include <float.h>
-#include <stdio.h>
#include "MEM_guardedalloc.h"
@@ -34,10 +31,10 @@
#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
@@ -50,19 +47,16 @@
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_tracking.h"
-#include "BKE_context.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
-#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-#include "ED_transform.h"
#include "ED_transform_snap_object_context.h"
#include "ED_view3d.h"
#include "ED_armature.h"
-#include "transform.h"
+#include "ED_transform.h"
/* -------------------------------------------------------------------- */
/** \name Internal Data Types
@@ -92,25 +86,27 @@ typedef struct SnapObjectData {
SNAP_MESH = 1,
SNAP_EDIT_MESH,
} type;
-} SnapObjectData;
-
-typedef struct SnapObjectData_Mesh {
- SnapObjectData sd;
- BVHTreeFromMesh treedata;
- const struct MPoly *poly;
- BVHTree *bvhtree[2]; /* from loose verts and from loose edges */
- uint has_looptris : 1;
- uint has_loose_edge : 1;
- uint has_loose_vert : 1;
-} SnapObjectData_Mesh;
+ BVHTree *bvhtree[2]; /* MESH: loose edges, loose verts
+ * EDIT_MESH: verts, edges. */
+ bool cached[2];
-typedef struct SnapObjectData_EditMesh {
- SnapObjectData sd;
- BVHTreeFromEditMesh *bvh_trees[3];
- float min[3], max[3];
-
-} SnapObjectData_EditMesh;
+ union {
+ struct {
+ /* SNAP_MESH */
+ BVHTreeFromMesh treedata_mesh;
+ const struct MPoly *poly;
+ uint has_looptris : 1;
+ uint has_loose_edge : 1;
+ uint has_loose_vert : 1;
+ };
+ struct {
+ /* SNAP_EDIT_MESH */
+ BVHTreeFromEditMesh treedata_editmesh;
+ float min[3], max[3];
+ };
+ };
+} SnapObjectData;
struct SnapObjectContext {
Main *bmain;
@@ -149,7 +145,7 @@ struct SnapObjectContext {
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Common Utilities
+/** \name Snap Object Data
* \{ */
/**
@@ -166,6 +162,45 @@ static void bm_mesh_minmax(BMesh *bm, float r_min[3], float r_max[3])
}
}
+static void snap_object_data_mesh_clear(SnapObjectData *sod)
+{
+ BLI_assert(sod->type == SNAP_MESH);
+ for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) {
+ if (!sod->cached[i]) {
+ BLI_bvhtree_free(sod->bvhtree[i]);
+ }
+ sod->bvhtree[i] = NULL;
+ }
+ free_bvhtree_from_mesh(&sod->treedata_mesh);
+}
+
+static void snap_object_data_editmesh_clear(SnapObjectData *sod)
+{
+ BLI_assert(sod->type == SNAP_EDIT_MESH);
+ for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) {
+ if (!sod->cached[i]) {
+ BLI_bvhtree_free(sod->bvhtree[i]);
+ }
+ sod->bvhtree[i] = NULL;
+ }
+ free_bvhtree_from_editmesh(&sod->treedata_editmesh);
+}
+
+static void snap_object_data_clear(SnapObjectData *sod)
+{
+ switch (sod->type) {
+ case SNAP_MESH: {
+ snap_object_data_mesh_clear(sod);
+ break;
+ }
+ case SNAP_EDIT_MESH: {
+ snap_object_data_editmesh_clear(sod);
+ break;
+ }
+ }
+ memset(&sod->type, 0x0, sizeof(*sod) - offsetof(SnapObjectData, type));
+}
+
static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object *ob)
{
SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
@@ -181,15 +216,17 @@ static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object *
return sod;
}
-static SnapObjectData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob)
+static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob)
{
void **sod_p;
if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_MESH);
}
else {
- SnapObjectData_Mesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
- sod->sd.type = SNAP_MESH;
+ SnapObjectData *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+
+ /* Init. */
+ sod->type = SNAP_MESH;
/* start assuming that it has each of these element types */
sod->has_looptris = true;
sod->has_loose_edge = true;
@@ -199,9 +236,9 @@ static SnapObjectData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, O
return *sod_p;
}
-static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx,
- Object *ob,
- BMEditMesh *em)
+static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
+ Object *ob,
+ BMEditMesh *em)
{
void **sod_p;
@@ -224,15 +261,23 @@ static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext
BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_EDIT_MESH);
}
else {
- SnapObjectData_EditMesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena,
- sizeof(*sod));
- sod->sd.type = SNAP_EDIT_MESH;
+ SnapObjectData *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+
+ /* Init. */
+ sod->type = SNAP_EDIT_MESH;
+ sod->treedata_editmesh.em = em;
bm_mesh_minmax(em->bm, sod->min, sod->max);
}
return *sod_p;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Iterator
+ * \{ */
+
typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx,
bool is_obedit,
bool use_backface_culling,
@@ -516,9 +561,9 @@ static bool raycastMesh(SnapObjectContext *sctx,
len_diff = 0.0f;
}
- SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
+ SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob);
- BVHTreeFromMesh *treedata = &sod->treedata;
+ BVHTreeFromMesh *treedata = &sod->treedata_mesh;
/* The tree is owned by the Mesh and may have been freed since we last used. */
if (treedata->tree) {
@@ -668,7 +713,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
local_depth *= local_scale;
}
- SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob, em);
+ SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob, em);
/* Test BoundBox */
@@ -690,24 +735,21 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
len_diff = 0.0f;
}
- if (sod->bvh_trees[2] == NULL) {
- sod->bvh_trees[2] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(BVHTreeFromEditMesh));
- }
-
- BVHTreeFromEditMesh *treedata = sod->bvh_trees[2];
+ BVHTreeFromEditMesh *treedata = &sod->treedata_editmesh;
BVHCache **em_bvh_cache = &((Mesh *)ob->data)->runtime.bvh_cache;
- if (sctx->callbacks.edit_mesh.test_face_fn == NULL) {
+ if (treedata->tree && treedata->cached) {
/* The tree is owned by the Mesh and may have been freed since we last used! */
- if (treedata->tree && !bvhcache_has_tree(*em_bvh_cache, treedata->tree)) {
- free_bvhtree_from_editmesh(treedata);
+ if (!bvhcache_has_tree(*em_bvh_cache, treedata->tree)) {
+ treedata->tree = NULL;
}
}
if (treedata->tree == NULL) {
/* Get original version of the edit_mesh. */
- BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
+ BLI_assert(sod->treedata_editmesh.em == BKE_editmesh_from_object(DEG_get_original_object(ob)));
+ BMEditMesh *em_orig = sod->treedata_editmesh.em;
if (sctx->callbacks.edit_mesh.test_face_fn) {
BMesh *bm = em_orig->bm;
@@ -796,7 +838,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
if (r_index) {
/* Get original version of the edit_mesh. */
- BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
+ BMEditMesh *em_orig = sod->treedata_editmesh.em;
*r_index = BM_elem_index_get(em_orig->looptris[hit.index][0]->f);
}
@@ -850,7 +892,10 @@ static bool raycastObj(SnapObjectContext *sctx,
Mesh *me = ob->data;
bool use_hide = false;
if (BKE_object_is_in_editmode(ob)) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
+ /* Strange, sometimes the `em` of the evaluated object has
+ * uninitialized memory. Need to be investigated.
+ * Use the `em` of the original object then. */
+ BMEditMesh *em = BKE_editmesh_from_object(DEG_get_original_object(ob));
if (use_obedit) {
retval = raycastEditMesh(sctx,
ray_start,
@@ -891,12 +936,13 @@ static bool raycastObj(SnapObjectContext *sctx,
case OB_CURVE:
case OB_SURF:
case OB_FONT: {
- if (ob->runtime.mesh_eval) {
+ Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
+ if (mesh_eval) {
retval = raycastMesh(sctx,
ray_start,
ray_dir,
ob,
- ob->runtime.mesh_eval,
+ mesh_eval,
obmat,
ob_index,
false,
@@ -1400,14 +1446,14 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
BLI_assert(sod != NULL);
if (sod->type == SNAP_MESH) {
- BVHTreeFromMesh *treedata = &((SnapObjectData_Mesh *)sod)->treedata;
+ BVHTreeFromMesh *treedata = &sod->treedata_mesh;
nearest2d.userdata = treedata;
nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
- const MPoly *mp = &((SnapObjectData_Mesh *)sod)->poly[*r_index];
+ const MPoly *mp = &sod->poly[*r_index];
const MLoop *ml = &treedata->loop[mp->loopstart];
if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
elem = SCE_SNAP_MODE_EDGE;
@@ -1435,7 +1481,7 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
}
else {
BLI_assert(sod->type == SNAP_EDIT_MESH);
- BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMEditMesh *em = sod->treedata_editmesh.em;
nearest2d.userdata = em;
nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
@@ -1525,14 +1571,14 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
nearest2d.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
nearest2d.use_backface_culling = use_backface_culling;
if (sod->type == SNAP_MESH) {
- nearest2d.userdata = &((SnapObjectData_Mesh *)sod)->treedata;
+ nearest2d.userdata = &sod->treedata_mesh;
nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
}
else {
BLI_assert(sod->type == SNAP_EDIT_MESH);
- nearest2d.userdata = BKE_editmesh_from_object(ob);
+ nearest2d.userdata = sod->treedata_editmesh.em;
nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get;
nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy;
@@ -2160,27 +2206,23 @@ static short snapMesh(SnapObjectContext *sctx,
return 0;
}
- SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
+ SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob);
BVHTreeFromMesh *treedata, dummy_treedata;
- BVHTree **bvhtree;
- treedata = &sod->treedata;
- bvhtree = sod->bvhtree;
+ treedata = &sod->treedata_mesh;
/* The tree is owned by the Mesh and may have been freed since we last used! */
- if ((sod->has_looptris && treedata->tree &&
- !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) ||
- (sod->has_loose_edge && bvhtree[0] &&
- !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0])) ||
- (sod->has_loose_vert && bvhtree[1] &&
- !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1]))) {
- BLI_assert(!treedata->tree || !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree));
- BLI_assert(!bvhtree[0] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0]));
- BLI_assert(!bvhtree[1] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1]));
-
+ if (treedata->cached && treedata->tree &&
+ !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) {
free_bvhtree_from_mesh(treedata);
- bvhtree[0] = NULL;
- bvhtree[1] = NULL;
+ }
+ if (sod->cached[0] && sod->bvhtree[0] &&
+ !bvhcache_has_tree(me->runtime.bvh_cache, sod->bvhtree[0])) {
+ sod->bvhtree[0] = NULL;
+ }
+ if (sod->cached[1] && sod->bvhtree[1] &&
+ !bvhcache_has_tree(me->runtime.bvh_cache, sod->bvhtree[1])) {
+ sod->bvhtree[1] = NULL;
}
if (sod->has_looptris && treedata->tree == NULL) {
@@ -2191,9 +2233,10 @@ static short snapMesh(SnapObjectContext *sctx,
treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
}
}
- if (sod->has_loose_edge && bvhtree[0] == NULL) {
- bvhtree[0] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEEDGES, 2);
- sod->has_loose_edge = bvhtree[0] != NULL;
+ if (sod->has_loose_edge && sod->bvhtree[0] == NULL) {
+ sod->bvhtree[0] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEEDGES, 2);
+ sod->has_loose_edge = sod->bvhtree[0] != NULL;
+ sod->cached[0] = dummy_treedata.cached;
if (sod->has_loose_edge) {
BLI_assert(treedata->vert_allocated == false);
@@ -2206,9 +2249,10 @@ static short snapMesh(SnapObjectContext *sctx,
}
}
if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- if (sod->has_loose_vert && bvhtree[1] == NULL) {
- bvhtree[1] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEVERTS, 2);
- sod->has_loose_vert = bvhtree[1] != NULL;
+ if (sod->has_loose_vert && sod->bvhtree[1] == NULL) {
+ sod->bvhtree[1] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEVERTS, 2);
+ sod->has_loose_vert = sod->bvhtree[1] != NULL;
+ sod->cached[1] = dummy_treedata.cached;
if (sod->has_loose_vert) {
BLI_assert(treedata->vert_allocated == false);
@@ -2226,7 +2270,7 @@ static short snapMesh(SnapObjectContext *sctx,
if (treedata->vert_allocated == false) {
treedata->vert = me->mvert; /* CustomData_get_layer(&me->vdata, CD_MVERT);? */
}
- if (treedata->tree || bvhtree[0]) {
+ if (treedata->tree || sod->bvhtree[0]) {
if (treedata->edge_allocated == false) {
/* If raycast has been executed before, `treedata->edge` can be NULL. */
treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
@@ -2263,9 +2307,9 @@ static short snapMesh(SnapObjectContext *sctx,
mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
}
- if (bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
+ if (sod->bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
/* snap to loose verts */
- BLI_bvhtree_find_nearest_projected(bvhtree[1],
+ BLI_bvhtree_find_nearest_projected(sod->bvhtree[1],
lpmat,
snapdata->win_size,
snapdata->mval,
@@ -2279,9 +2323,9 @@ static short snapMesh(SnapObjectContext *sctx,
}
if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- if (bvhtree[0]) {
+ if (sod->bvhtree[0]) {
/* snap to loose edges */
- BLI_bvhtree_find_nearest_projected(bvhtree[0],
+ BLI_bvhtree_find_nearest_projected(sod->bvhtree[0],
lpmat,
snapdata->win_size,
snapdata->mval,
@@ -2311,9 +2355,9 @@ static short snapMesh(SnapObjectContext *sctx,
}
else {
BLI_assert(snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX);
- if (bvhtree[0]) {
- /* snap to loose edges */
- BLI_bvhtree_find_nearest_projected(bvhtree[0],
+ if (sod->bvhtree[0]) {
+ /* snap to loose edge verts */
+ BLI_bvhtree_find_nearest_projected(sod->bvhtree[0],
lpmat,
snapdata->win_size,
snapdata->mval,
@@ -2325,7 +2369,7 @@ static short snapMesh(SnapObjectContext *sctx,
}
if (treedata->tree) {
- /* snap to looptris */
+ /* snap to looptri verts */
BLI_bvhtree_find_nearest_projected(treedata->tree,
lpmat,
snapdata->win_size,
@@ -2388,17 +2432,12 @@ static short snapEditMesh(SnapObjectContext *sctx,
}
}
- BVHTreeFromEditMesh *treedata_vert = NULL, *treedata_edge = NULL;
-
- BLI_assert(BKE_object_get_pre_modified_mesh(ob) == BKE_object_get_pre_modified_mesh(ob));
- UNUSED_VARS_NDEBUG(ob);
-
float lpmat[4][4];
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
float dist_px_sq = SQUARE(*dist_px);
- SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob, em);
+ SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob, em);
/* Test BoundBox */
@@ -2411,19 +2450,16 @@ static short snapEditMesh(SnapObjectContext *sctx,
BVHCache **em_bvh_cache = &((Mesh *)ob->data)->runtime.bvh_cache;
if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- if (sod->bvh_trees[0] == NULL) {
- sod->bvh_trees[0] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
- }
- treedata_vert = sod->bvh_trees[0];
+ BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[0]};
- if (sctx->callbacks.edit_mesh.test_vert_fn == NULL) {
+ if (treedata.tree && sod->cached[0]) {
/* The tree is owned by the Mesh and may have been freed since we last used! */
- if (treedata_vert->tree && !bvhcache_has_tree(*em_bvh_cache, treedata_vert->tree)) {
- free_bvhtree_from_editmesh(treedata_vert);
+ if (!bvhcache_has_tree(*em_bvh_cache, treedata.tree)) {
+ treedata.tree = sod->bvhtree[0] = NULL;
}
}
- if (treedata_vert->tree == NULL) {
+ if (treedata.tree == NULL) {
BLI_bitmap *verts_mask = NULL;
int verts_num_active = -1;
if (sctx->callbacks.edit_mesh.test_vert_fn) {
@@ -2436,29 +2472,28 @@ static short snapEditMesh(SnapObjectContext *sctx,
sctx->callbacks.edit_mesh.user_data);
bvhtree_from_editmesh_verts_ex(
- treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL);
+ &treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL);
MEM_freeN(verts_mask);
}
else {
- BKE_bvhtree_from_editmesh_get(treedata_vert, em, 2, BVHTREE_FROM_EM_VERTS, em_bvh_cache);
+ BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_VERTS, em_bvh_cache);
}
+ sod->bvhtree[0] = treedata.tree;
+ sod->cached[0] = treedata.cached;
}
}
if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- if (sod->bvh_trees[1] == NULL) {
- sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
- }
- treedata_edge = sod->bvh_trees[1];
+ BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[1]};
- if (sctx->callbacks.edit_mesh.test_edge_fn == NULL) {
+ if (treedata.tree && sod->cached[1]) {
/* The tree is owned by the Mesh and may have been freed since we last used! */
- if (treedata_edge->tree && !bvhcache_has_tree(*em_bvh_cache, treedata_edge->tree)) {
- free_bvhtree_from_editmesh(treedata_edge);
+ if (!bvhcache_has_tree(*em_bvh_cache, treedata.tree)) {
+ treedata.tree = sod->bvhtree[1] = NULL;
}
}
- if (treedata_edge->tree == NULL) {
+ if (treedata.tree == NULL) {
BLI_bitmap *edges_mask = NULL;
int edges_num_active = -1;
if (sctx->callbacks.edit_mesh.test_edge_fn) {
@@ -2471,12 +2506,14 @@ static short snapEditMesh(SnapObjectContext *sctx,
sctx->callbacks.edit_mesh.user_data);
bvhtree_from_editmesh_edges_ex(
- treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL);
+ &treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL);
MEM_freeN(edges_mask);
}
else {
- BKE_bvhtree_from_editmesh_get(treedata_edge, em, 2, BVHTREE_FROM_EM_EDGES, em_bvh_cache);
+ BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_EDGES, em_bvh_cache);
}
+ sod->bvhtree[1] = treedata.tree;
+ sod->cached[1] = treedata.cached;
}
}
@@ -2502,10 +2539,10 @@ static short snapEditMesh(SnapObjectContext *sctx,
mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
}
- if (treedata_vert && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
+ if (sod->bvhtree[0] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
- BLI_bvhtree_find_nearest_projected(treedata_vert->tree,
+ BLI_bvhtree_find_nearest_projected(sod->bvhtree[0],
lpmat,
snapdata->win_size,
snapdata->mval,
@@ -2516,12 +2553,12 @@ static short snapEditMesh(SnapObjectContext *sctx,
&nearest2d);
}
- if (treedata_edge && (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE)) {
+ if (sod->bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE)) {
int last_index = nearest.index;
nearest.index = -1;
BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT);
BM_mesh_elem_index_ensure(em->bm, BM_EDGE | BM_VERT);
- BLI_bvhtree_find_nearest_projected(treedata_edge->tree,
+ BLI_bvhtree_find_nearest_projected(sod->bvhtree[1],
lpmat,
snapdata->win_size,
snapdata->mval,
@@ -2588,7 +2625,10 @@ static short snapObject(SnapObjectContext *sctx,
case OB_MESH: {
Mesh *me = ob->data;
if (BKE_object_is_in_editmode(ob)) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
+ /* Strange, sometimes the `em` of the evaluated object has
+ * uninitialized memory. Need to be investigated.
+ * Use the `em` of the original object then. */
+ BMEditMesh *em = BKE_editmesh_from_object(DEG_get_original_object(ob));
if (use_obedit) {
retval = snapEditMesh(
sctx, snapdata, ob, em, obmat, use_backface_culling, dist_px, r_loc, r_no, r_index);
@@ -2615,11 +2655,12 @@ static short snapObject(SnapObjectContext *sctx,
break; /* Use ATTR_FALLTHROUGH if we want to snap to the generated mesh. */
case OB_SURF:
case OB_FONT: {
- if (ob->runtime.mesh_eval) {
+ Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
+ if (mesh_eval) {
retval |= snapMesh(sctx,
snapdata,
ob,
- ob->runtime.mesh_eval,
+ mesh_eval,
obmat,
use_backface_culling,
dist_px,
@@ -2794,24 +2835,8 @@ SnapObjectContext *ED_transform_snap_object_context_create_view3d(Main *bmain,
static void snap_object_data_free(void *sod_v)
{
- switch (((SnapObjectData *)sod_v)->type) {
- case SNAP_MESH: {
- SnapObjectData_Mesh *sod = sod_v;
- if (sod->treedata.tree) {
- free_bvhtree_from_mesh(&sod->treedata);
- }
- break;
- }
- case SNAP_EDIT_MESH: {
- SnapObjectData_EditMesh *sod = sod_v;
- for (int i = 0; i < ARRAY_SIZE(sod->bvh_trees); i++) {
- if (sod->bvh_trees[i]) {
- free_bvhtree_from_editmesh(sod->bvh_trees[i]);
- }
- }
- break;
- }
- }
+ SnapObjectData *sod = sod_v;
+ snap_object_data_clear(sod);
}
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 43ccc1a8250..72376b977eb 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -238,15 +238,12 @@ bool ED_editors_flush_edits_for_object_ex(Main *bmain,
/* Don't allow flushing while in the middle of a stroke (frees data in use).
* Auto-save prevents this from happening but scripts
* may cause a flush on saving: T53986. */
- if ((ob->sculpt && ob->sculpt->cache) == 0) {
-
- {
- char *needs_flush_ptr = &ob->sculpt->needs_flush_to_id;
- if (check_needs_flush && (*needs_flush_ptr == 0)) {
- return false;
- }
- *needs_flush_ptr = 0;
+ if (!ELEM(NULL, ob->sculpt, ob->sculpt->cache)) {
+ char *needs_flush_ptr = &ob->sculpt->needs_flush_to_id;
+ if (check_needs_flush && (*needs_flush_ptr == 0)) {
+ return false;
}
+ *needs_flush_ptr = 0;
/* flush multires changes (for sculpt) */
multires_flush_sculpt_updates(ob);