diff options
Diffstat (limited to 'source/blender/editors')
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); |