diff options
Diffstat (limited to 'source/blender/editors/transform')
62 files changed, 2572 insertions, 1545 deletions
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index 68c4f4e76ca..ec6f62e0f5b 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -15,7 +15,6 @@ set(INC ../../render ../../sequencer ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna @@ -39,6 +38,7 @@ set(SRC transform_convert_mesh_edge.c transform_convert_mesh_skin.c transform_convert_mesh_uv.c + transform_convert_mesh_vert_cdata.c transform_convert_nla.c transform_convert_node.c transform_convert_object.c diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 960d9a25ca7..eb46da3579a 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -19,6 +19,7 @@ #include "BKE_context.h" #include "BKE_editmesh.h" +#include "BKE_layer.h" #include "BKE_mask.h" #include "BKE_scene.h" @@ -484,7 +485,9 @@ static void viewRedrawForce(const bContext *C, TransInfo *t) /* XXX how to deal with lock? */ SpaceImage *sima = (SpaceImage *)t->area->spacedata.first; if (sima->lock) { - WM_event_add_notifier(C, NC_GEOM | ND_DATA, OBEDIT_FROM_VIEW_LAYER(t->view_layer)->data); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + WM_event_add_notifier( + C, NC_GEOM | ND_DATA, BKE_view_layer_edit_object_get(t->view_layer)->data); } else { ED_area_tag_redraw(t->area); @@ -525,7 +528,8 @@ static void viewRedrawPost(bContext *C, TransInfo *t) UVCALC_TRANSFORM_CORRECT_SLIDE : UVCALC_TRANSFORM_CORRECT; - if ((t->data_type == TC_MESH_VERTS) && (t->settings->uvcalc_flag & uvcalc_correct_flag)) { + if ((t->data_type == &TransConvertType_Mesh) && + (t->settings->uvcalc_flag & uvcalc_correct_flag)) { WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); } @@ -847,7 +851,7 @@ static bool transform_event_modal_constraint(TransInfo *t, short modal_type) return false; } - if (t->data_type == TC_SEQ_IMAGE_DATA) { + if (t->data_type == &TransConvertType_SequencerImage) { /* Setup the 2d msg string so it writes out the transform space. */ msg_2d = msg_3d; @@ -1327,7 +1331,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) handled = true; } - if (t->redraw && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { + if (t->redraw && !ISMOUSE_MOTION(event->type)) { WM_window_status_area_tag_redraw(CTX_wm_window(t->context)); } @@ -1475,7 +1479,8 @@ static void drawTransformPixel(const struct bContext *C, ARegion *region, void * if (region == t->region) { Scene *scene = t->scene; ViewLayer *view_layer = t->view_layer; - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); /* draw auto-key-framing hint in the corner * - only draw if enabled (advanced users may be distracted/annoyed), @@ -1535,7 +1540,8 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) if (!(t->options & CTX_NO_PET)) { if ((prop = RNA_struct_find_property(op->ptr, "use_proportional_edit")) && !RNA_property_is_set(op->ptr, prop)) { - const Object *obact = OBACT(t->view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + const Object *obact = BKE_view_layer_active_object_get(t->view_layer); if (t->spacetype == SPACE_GRAPH) { ts->proportional_fcurve = use_prop_edit; @@ -1577,7 +1583,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) if (transformModeUseSnap(t)) { if (!(t->modifiers & MOD_SNAP) != !(t->tsnap.flag & SCE_SNAP)) { /* Type is #eSnapFlag, but type must match various snap attributes in #ToolSettings. */ - char *snap_flag_ptr; + short *snap_flag_ptr; wmMsgParams_RNA msg_key_params = {{0}}; RNA_pointer_create(&t->scene->id, &RNA_ToolSettings, ts, &msg_key_params.ptr); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index a35942aedec..09fc07f57f4 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -38,6 +38,7 @@ struct ReportList; struct Scene; struct ScrArea; struct SnapObjectContext; +struct TransConvertTypeInfo; struct TransDataContainer; struct TransInfo; struct TransSnap; @@ -204,36 +205,6 @@ typedef enum { HLP_TRACKBALL = 6, } eTHelpline; -typedef enum { - TC_NONE = 0, - TC_ACTION_DATA, - TC_POSE, - TC_ARMATURE_VERTS, - TC_CURSOR_IMAGE, - TC_CURSOR_SEQUENCER, - TC_CURSOR_VIEW3D, - TC_CURVE_VERTS, - TC_GRAPH_EDIT_DATA, - TC_GPENCIL, - TC_LATTICE_VERTS, - TC_MASKING_DATA, - TC_MBALL_VERTS, - TC_MESH_VERTS, - TC_MESH_EDGES, - TC_MESH_SKIN, - TC_MESH_UV, - TC_NLA_DATA, - TC_NODE_DATA, - TC_OBJECT, - TC_OBJECT_TEXSPACE, - TC_PAINT_CURVE_VERTS, - TC_PARTICLE_VERTS, - TC_SCULPT, - TC_SEQ_DATA, - TC_SEQ_IMAGE_DATA, - TC_TRACKING_DATA, -} eTConvertType; - /** \} */ /* -------------------------------------------------------------------- */ @@ -306,9 +277,9 @@ typedef struct TransSnap { eSnapTargetSelect target_select; bool align; bool project; - bool snap_self; bool peel; bool use_backface_culling; + short face_nearest_steps; eTSnap status; /* Snapped Element Type (currently for objects only). */ eSnapMode snapElem; @@ -384,10 +355,12 @@ typedef struct MouseInput { /** Initial mouse position. */ int imval[2]; - bool precision; - float precision_factor; + float imval_unproj[3]; float center[2]; float factor; + float precision_factor; + bool precision; + /** Additional data, if needed by the particular function. */ void *data; @@ -463,6 +436,8 @@ typedef struct TransDataContainer { int data_len; /** Total number of transformed data_mirror. */ int data_mirror_len; + /** Total number of transformed gp-frames. */ + int data_gpf_len; struct Object *obedit; @@ -516,7 +491,7 @@ typedef struct TransInfo { int data_len_all; /** TODO: It should be a member of #TransDataContainer. */ - eTConvertType data_type; + struct TransConvertTypeInfo *data_type; /** Current context/options for transform. */ eTContext options; @@ -645,6 +620,9 @@ typedef struct TransInfo { * value of the input parameter, except when a constrain is entered. */ float values_final[4]; + /** Cache safe value for constraints that require iteration or are slow to calculate. */ + float values_inside_constraints[4]; + /* Axis members for modes that use an axis separate from the orientation (rotate & shear). */ /** Primary axis, rotate only uses this. */ @@ -683,6 +661,9 @@ typedef struct TransInfo { /** Typically for mode settings. */ TransCustomDataContainer custom; + + /* Needed for sculpt transform. */ + const char *undo_name; } TransInfo; /** \} */ @@ -782,6 +763,7 @@ void applyMouseInput(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]); +void transform_input_update(TransInfo *t, const float fac); void setCustomPoints(TransInfo *t, MouseInput *mi, const int start[2], const int end[2]); void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[2]); @@ -830,6 +812,7 @@ void calculateCenter2D(TransInfo *t); void calculateCenterLocal(TransInfo *t, const float center_global[3]); void calculateCenter(TransInfo *t); +void tranformViewUpdate(TransInfo *t); /* API functions for getting center points */ void calculateCenterBound(TransInfo *t, float r_center[3]); diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 0bb00032561..2e12611a7c9 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -177,7 +177,7 @@ static void axisProjection(const TransInfo *t, const float in[3], float out[3]) { - float norm[3], vec[3], factor, angle; + float vec[3], factor, angle; float t_con_center[3]; if (is_zero_v3(in)) { @@ -214,7 +214,7 @@ static void axisProjection(const TransInfo *t, } else { float v[3]; - float norm_center[3]; + float norm[3], norm_center[3]; float plane[3]; view_vector_calc(t, t_con_center, norm_center); @@ -402,7 +402,7 @@ static void applyAxisConstraintVec(const TransInfo *t, if (activeSnap(t)) { if (validSnap(t)) { is_snap_to_edge = (t->tsnap.snapElem & SCE_SNAP_MODE_EDGE) != 0; - is_snap_to_face = (t->tsnap.snapElem & SCE_SNAP_MODE_FACE) != 0; + is_snap_to_face = (t->tsnap.snapElem & SCE_SNAP_MODE_FACE_RAYCAST) != 0; is_snap_to_point = !is_snap_to_edge && !is_snap_to_face; } else if (t->tsnap.snapElem & SCE_SNAP_MODE_GRID) { @@ -701,12 +701,12 @@ void setLocalConstraint(TransInfo *t, int mode, const char text[]) } } -void setUserConstraint(TransInfo *t, int mode, const char ftext[]) +void setUserConstraint(TransInfo *t, int mode, const char text_[]) { char text[256]; const short orientation = transform_orientation_or_default(t); const char *spacename = transform_orientations_spacename_get(t, orientation); - BLI_snprintf(text, sizeof(text), ftext, spacename); + BLI_snprintf(text, sizeof(text), text_, spacename); switch (orientation) { case V3D_ORIENT_LOCAL: diff --git a/source/blender/editors/transform/transform_constraints.h b/source/blender/editors/transform/transform_constraints.h index 9182330b729..90a693b089e 100644 --- a/source/blender/editors/transform/transform_constraints.h +++ b/source/blender/editors/transform/transform_constraints.h @@ -34,7 +34,7 @@ void setLocalConstraint(TransInfo *t, int mode, const char text[]); * `ftext` is a format string passed to #BLI_snprintf. It will add the name of * the orientation where %s is (logically). */ -void setUserConstraint(TransInfo *t, int mode, const char text[]); +void setUserConstraint(TransInfo *t, int mode, const char text_[]); void drawConstraint(TransInfo *t); /** * Called from drawview.c, as an extra per-window draw option. diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index d9b971c5478..1e29411fe84 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -479,132 +479,6 @@ TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTr /** \name UV Coordinates * \{ */ -/** - * Find the correction for the scaling factor when "Constrain to Bounds" is active. - * \param numerator: How far the UV boundary (unit square) is from the origin of the scale. - * \param denominator: How far the AABB is from the origin of the scale. - * \param scale: Scale parameter to update. - */ -static void constrain_scale_to_boundary(const float numerator, - const float denominator, - float *scale) -{ - if (denominator == 0.0f) { - /* The origin of the scale is on the edge of the boundary. */ - if (numerator < 0.0f) { - /* Negative scale will wrap around and put us outside the boundary. */ - *scale = 0.0f; /* Hold at the boundary instead. */ - } - return; /* Nothing else we can do without more info. */ - } - - const float correction = numerator / denominator; - if (correction < 0.0f || !isfinite(correction)) { - /* TODO: Correction is negative or invalid, but we lack context to fix `*scale`. */ - return; - } - - if (denominator < 0.0f) { - /* Scale origin is outside boundary, only make scale bigger. */ - if (*scale < correction) { - *scale = correction; - } - return; - } - - /* Scale origin is inside boundary, the "regular" case, limit maximum scale. */ - if (*scale > correction) { - *scale = correction; - } -} - -bool clipUVTransform(TransInfo *t, float vec[2], const bool resize) -{ - bool clipx = true, clipy = true; - float min[2], max[2]; - - /* Check if the current image in UV editor is a tiled image or not. */ - const SpaceImage *sima = t->area->spacedata.first; - const Image *image = sima->image; - const bool is_tiled_image = image && (image->source == IMA_SRC_TILED); - /* Stores the coordinates of the closest UDIM tile. - * Also acts as an offset to the tile from the origin of UV space. */ - float base_offset[2] = {0.0f, 0.0f}; - - /* If tiled image then constrain to correct/closest UDIM tile, else 0-1 UV space. */ - if (is_tiled_image) { - int nearest_tile_index = BKE_image_find_nearest_tile(image, t->center_global); - if (nearest_tile_index != -1) { - nearest_tile_index -= 1001; - /* Getting coordinates of nearest tile from the tile index. */ - base_offset[0] = nearest_tile_index % 10; - base_offset[1] = nearest_tile_index / 10; - } - } - - min[0] = min[1] = FLT_MAX; - max[0] = max[1] = FLT_MIN; - - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - - TransData *td; - int a; - - for (a = 0, td = tc->data; a < tc->data_len; a++, td++) { - minmax_v2v2_v2(min, max, td->loc); - } - } - - if (resize) { - /* Assume no change is required. */ - float scalex = 1.0f; - float scaley = 1.0f; - - /* Update U against the left border. */ - constrain_scale_to_boundary( - t->center_global[0] - base_offset[0], t->center_global[0] - min[0], &scalex); - /* Now the right border, negated, because `-1.0 / -1.0 = 1.0` */ - constrain_scale_to_boundary(base_offset[0] + t->aspect[0] - t->center_global[0], - max[0] - t->center_global[0], - &scalex); - - /* Do the same for the V co-ordinate, which is called `y`. */ - constrain_scale_to_boundary( - t->center_global[1] - base_offset[1], t->center_global[1] - min[1], &scaley); - constrain_scale_to_boundary(base_offset[1] + t->aspect[1] - t->center_global[1], - max[1] - t->center_global[1], - &scaley); - - clipx = (scalex != 1.0f); - clipy = (scaley != 1.0f); - vec[0] *= scalex; - vec[1] *= scaley; - } - else { - if (min[0] < base_offset[0]) { - vec[0] += base_offset[0] - min[0]; - } - else if (max[0] > base_offset[0] + t->aspect[0]) { - vec[0] -= max[0] - base_offset[0] - t->aspect[0]; - } - else { - clipx = 0; - } - - if (min[1] < base_offset[1]) { - vec[1] += base_offset[1] - min[1]; - } - else if (max[1] > base_offset[1] + t->aspect[1]) { - vec[1] -= max[1] - base_offset[1] - t->aspect[1]; - } - else { - clipy = 0; - } - } - - return (clipx || clipy); -} - void clipUVData(TransInfo *t) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { @@ -769,7 +643,7 @@ void posttrans_fcurve_clean(FCurve *fcu, const int sel_flag, const bool use_hand } else { /* Delete Keyframe */ - delete_fcurve_key(fcu, i, 0); + BKE_fcurve_delete_key(fcu, i); } /* Update count of how many we've deleted @@ -779,7 +653,7 @@ void posttrans_fcurve_clean(FCurve *fcu, const int sel_flag, const bool use_hand } else { /* Always delete - Unselected keys don't matter */ - delete_fcurve_key(fcu, i, 0); + BKE_fcurve_delete_key(fcu, i); } /* Stop the RK search... we've found our match now */ @@ -902,62 +776,12 @@ void special_aftertrans_update(bContext *C, TransInfo *t) return; } - BLI_assert(CTX_data_main(t->context) == CTX_data_main(C)); - switch (t->data_type) { - case TC_ACTION_DATA: - special_aftertrans_update__actedit(C, t); - break; - case TC_POSE: - special_aftertrans_update__pose(C, t); - break; - case TC_GRAPH_EDIT_DATA: - special_aftertrans_update__graph(C, t); - break; - case TC_MASKING_DATA: - special_aftertrans_update__mask(C, t); - break; - case TC_MESH_VERTS: - case TC_MESH_EDGES: - special_aftertrans_update__mesh(C, t); - break; - case TC_NLA_DATA: - special_aftertrans_update__nla(C, t); - break; - case TC_NODE_DATA: - special_aftertrans_update__node(C, t); - break; - case TC_OBJECT: - special_aftertrans_update__object(C, t); - break; - case TC_SCULPT: - special_aftertrans_update__sculpt(C, t); - break; - case TC_SEQ_DATA: - special_aftertrans_update__sequencer(C, t); - break; - case TC_SEQ_IMAGE_DATA: - special_aftertrans_update__sequencer_image(C, t); - break; - case TC_TRACKING_DATA: - special_aftertrans_update__movieclip(C, t); - break; - case TC_ARMATURE_VERTS: - case TC_CURSOR_IMAGE: - case TC_CURSOR_SEQUENCER: - case TC_CURSOR_VIEW3D: - case TC_CURVE_VERTS: - case TC_GPENCIL: - case TC_LATTICE_VERTS: - case TC_MBALL_VERTS: - case TC_MESH_UV: - case TC_MESH_SKIN: - case TC_OBJECT_TEXSPACE: - case TC_PAINT_CURVE_VERTS: - case TC_PARTICLE_VERTS: - case TC_NONE: - default: - break; + if (!t->data_type || !t->data_type->special_aftertrans_update) { + return; } + + BLI_assert(CTX_data_main(t->context) == CTX_data_main(C)); + t->data_type->special_aftertrans_update(C, t); } int special_transform_moving(TransInfo *t) @@ -1018,54 +842,44 @@ static int countAndCleanTransDataContainer(TransInfo *t) static void init_proportional_edit(TransInfo *t) { - eTConvertType convert_type = t->data_type; - switch (convert_type) { - case TC_ACTION_DATA: - case TC_CURVE_VERTS: - case TC_GRAPH_EDIT_DATA: - case TC_GPENCIL: - case TC_LATTICE_VERTS: - case TC_MASKING_DATA: - case TC_MBALL_VERTS: - case TC_MESH_VERTS: - case TC_MESH_EDGES: - case TC_MESH_SKIN: - case TC_MESH_UV: - case TC_NODE_DATA: - case TC_OBJECT: - case TC_PARTICLE_VERTS: - break; - case TC_POSE: /* Disable PET, its not usable in pose mode yet T32444. */ - case TC_ARMATURE_VERTS: - case TC_CURSOR_IMAGE: - case TC_CURSOR_SEQUENCER: - case TC_CURSOR_VIEW3D: - case TC_NLA_DATA: - case TC_OBJECT_TEXSPACE: - case TC_PAINT_CURVE_VERTS: - case TC_SCULPT: - case TC_SEQ_DATA: - case TC_SEQ_IMAGE_DATA: - case TC_TRACKING_DATA: - case TC_NONE: - default: - t->options |= CTX_NO_PET; - t->flag &= ~T_PROP_EDIT_ALL; - return; + /* NOTE: PET is not usable in pose mode yet T32444. */ + if (!ELEM(t->data_type, + &TransConvertType_Action, + &TransConvertType_Curve, + &TransConvertType_Graph, + &TransConvertType_GPencil, + &TransConvertType_Lattice, + &TransConvertType_Mask, + &TransConvertType_MBall, + &TransConvertType_Mesh, + &TransConvertType_MeshEdge, + &TransConvertType_MeshSkin, + &TransConvertType_MeshUV, + &TransConvertType_MeshVertCData, + &TransConvertType_Node, + &TransConvertType_Object, + &TransConvertType_Particle)) { + /* Disable PET */ + t->options |= CTX_NO_PET; + t->flag &= ~T_PROP_EDIT_ALL; + return; } if (t->data_len_all && (t->flag & T_PROP_EDIT)) { - if (convert_type == TC_OBJECT) { + if (t->data_type == &TransConvertType_Object) { /* Selected objects are already first, no need to presort. */ } else { sort_trans_data_selected_first(t); } - if (ELEM(convert_type, TC_ACTION_DATA, TC_GRAPH_EDIT_DATA)) { + if (ELEM(t->data_type, &TransConvertType_Action, &TransConvertType_Graph)) { /* Distance has already been set. */ } - else if (ELEM(convert_type, TC_MESH_VERTS, TC_MESH_SKIN)) { + else if (ELEM(t->data_type, + &TransConvertType_Mesh, + &TransConvertType_MeshSkin, + &TransConvertType_MeshVertCData)) { if (t->flag & T_PROP_CONNECTED) { /* Already calculated by transform_convert_mesh_connectivity_distance. */ } @@ -1073,10 +887,10 @@ static void init_proportional_edit(TransInfo *t) set_prop_dist(t, false); } } - else if (convert_type == TC_MESH_UV && t->flag & T_PROP_CONNECTED) { + else if (t->data_type == &TransConvertType_MeshUV && t->flag & T_PROP_CONNECTED) { /* Already calculated by uv_set_connectivity_distance. */ } - else if (convert_type == TC_CURVE_VERTS) { + else if (t->data_type == &TransConvertType_Curve) { BLI_assert(t->obedit_type == OB_CURVES_LEGACY); set_prop_dist(t, false); } @@ -1099,44 +913,26 @@ static void init_TransDataContainers(TransInfo *t, Object **objects, uint objects_len) { - switch (t->data_type) { - case TC_POSE: - case TC_ARMATURE_VERTS: - case TC_CURVE_VERTS: - case TC_GPENCIL: - case TC_LATTICE_VERTS: - case TC_MBALL_VERTS: - case TC_MESH_VERTS: - case TC_MESH_EDGES: - case TC_MESH_SKIN: - case TC_MESH_UV: - break; - case TC_ACTION_DATA: - case TC_GRAPH_EDIT_DATA: - case TC_CURSOR_IMAGE: - case TC_CURSOR_SEQUENCER: - case TC_CURSOR_VIEW3D: - case TC_MASKING_DATA: - case TC_NLA_DATA: - case TC_NODE_DATA: - case TC_OBJECT: - case TC_OBJECT_TEXSPACE: - case TC_PAINT_CURVE_VERTS: - case TC_PARTICLE_VERTS: - case TC_SCULPT: - case TC_SEQ_DATA: - case TC_SEQ_IMAGE_DATA: - case TC_TRACKING_DATA: - case TC_NONE: - default: - /* Does not support Multi object editing. */ - return; + if (!ELEM(t->data_type, + &TransConvertType_Pose, + &TransConvertType_EditArmature, + &TransConvertType_Curve, + &TransConvertType_GPencil, + &TransConvertType_Lattice, + &TransConvertType_MBall, + &TransConvertType_Mesh, + &TransConvertType_MeshEdge, + &TransConvertType_MeshSkin, + &TransConvertType_MeshUV, + &TransConvertType_MeshVertCData)) { + /* Does not support Multi object editing. */ + return; } const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT; const short object_type = obact ? obact->type : -1; - if ((object_mode & OB_MODE_EDIT) || (t->data_type == TC_GPENCIL) || + if ((object_mode & OB_MODE_EDIT) || (t->data_type == &TransConvertType_GPencil) || ((object_mode & OB_MODE_POSE) && (object_type == OB_ARMATURE))) { if (t->data_container) { MEM_freeN(t->data_container); @@ -1144,15 +940,16 @@ static void init_TransDataContainers(TransInfo *t, bool free_objects = false; if (objects == NULL) { - objects = BKE_view_layer_array_from_objects_in_mode( + struct ObjectsInModeParams params = {0}; + params.object_mode = object_mode; + /* Pose transform operates on `ob->pose` so don't skip duplicate object-data. */ + params.no_dup_data = (object_mode & OB_MODE_POSE) == 0; + objects = BKE_view_layer_array_from_objects_in_mode_params( + t->scene, t->view_layer, (t->spacetype == SPACE_VIEW3D) ? t->view : NULL, &objects_len, - { - .object_mode = object_mode, - /* Pose transform operates on `ob->pose` so don't skip duplicate object-data. */ - .no_dup_data = (object_mode & OB_MODE_POSE) == 0, - }); + ¶ms); free_objects = true; } @@ -1178,7 +975,7 @@ static void init_TransDataContainers(TransInfo *t, tc->poseobj = objects[i]; tc->use_local_mat = true; } - else if (t->data_type == TC_GPENCIL) { + else if (t->data_type == &TransConvertType_GPencil) { tc->use_local_mat = true; } @@ -1201,173 +998,132 @@ static void init_TransDataContainers(TransInfo *t, } } -static eTFlag flags_from_data_type(eTConvertType data_type) -{ - switch (data_type) { - case TC_ACTION_DATA: - case TC_GRAPH_EDIT_DATA: - case TC_MASKING_DATA: - case TC_NLA_DATA: - case TC_NODE_DATA: - case TC_PAINT_CURVE_VERTS: - case TC_SEQ_DATA: - case TC_SEQ_IMAGE_DATA: - case TC_TRACKING_DATA: - return T_POINTS | T_2D_EDIT; - case TC_ARMATURE_VERTS: - case TC_CURVE_VERTS: - case TC_GPENCIL: - case TC_LATTICE_VERTS: - case TC_MBALL_VERTS: - case TC_MESH_VERTS: - case TC_MESH_SKIN: - return T_EDIT | T_POINTS; - case TC_MESH_EDGES: - return T_EDIT; - case TC_MESH_UV: - return T_EDIT | T_POINTS | T_2D_EDIT; - case TC_CURSOR_IMAGE: - case TC_CURSOR_SEQUENCER: - return T_2D_EDIT; - case TC_PARTICLE_VERTS: - return T_POINTS; - case TC_POSE: - case TC_CURSOR_VIEW3D: - case TC_OBJECT: - case TC_OBJECT_TEXSPACE: - case TC_SCULPT: - case TC_NONE: - default: - break; - } - return 0; -} - -static eTConvertType convert_type_get(const TransInfo *t, Object **r_obj_armature) +static TransConvertTypeInfo *convert_type_get(const TransInfo *t, Object **r_obj_armature) { ViewLayer *view_layer = t->view_layer; - Object *ob = OBACT(view_layer); - eTConvertType convert_type = TC_NONE; + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); /* if tests must match recalcData for correct updates */ if (t->options & CTX_CURSOR) { if (t->spacetype == SPACE_IMAGE) { - convert_type = TC_CURSOR_IMAGE; - } - else if (t->spacetype == SPACE_SEQ) { - convert_type = TC_CURSOR_SEQUENCER; + return &TransConvertType_CursorImage; } - else { - convert_type = TC_CURSOR_VIEW3D; + + if (t->spacetype == SPACE_SEQ) { + return &TransConvertType_CursorSequencer; } + + return &TransConvertType_Cursor3D; } - else if (!(t->options & CTX_PAINT_CURVE) && (t->spacetype == SPACE_VIEW3D) && ob && - (ob->mode == OB_MODE_SCULPT) && ob->sculpt) { - convert_type = TC_SCULPT; + if (!(t->options & CTX_PAINT_CURVE) && (t->spacetype == SPACE_VIEW3D) && ob && + (ob->mode == OB_MODE_SCULPT) && ob->sculpt) { + return &TransConvertType_Sculpt; } - else if (t->options & CTX_TEXTURE_SPACE) { - convert_type = TC_OBJECT_TEXSPACE; + if (t->options & CTX_TEXTURE_SPACE) { + return &TransConvertType_ObjectTexSpace; } - else if (t->options & CTX_EDGE_DATA) { - convert_type = TC_MESH_EDGES; + if (t->options & CTX_EDGE_DATA) { + return &TransConvertType_MeshEdge; } - else if (t->options & CTX_GPENCIL_STROKES) { - convert_type = TC_GPENCIL; + if (t->options & CTX_GPENCIL_STROKES) { + return &TransConvertType_GPencil; } - else if (t->spacetype == SPACE_IMAGE) { + if (t->spacetype == SPACE_IMAGE) { if (t->options & CTX_MASK) { - convert_type = TC_MASKING_DATA; + return &TransConvertType_Mask; } - else if (t->options & CTX_PAINT_CURVE) { + if (t->options & CTX_PAINT_CURVE) { if (!ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) { - convert_type = TC_PAINT_CURVE_VERTS; + return &TransConvertType_PaintCurve; } } else if (t->obedit_type == OB_MESH) { - convert_type = TC_MESH_UV; + return &TransConvertType_MeshUV; } + return NULL; } - else if (t->spacetype == SPACE_ACTION) { - convert_type = TC_ACTION_DATA; + if (t->spacetype == SPACE_ACTION) { + return &TransConvertType_Action; } - else if (t->spacetype == SPACE_NLA) { - convert_type = TC_NLA_DATA; + if (t->spacetype == SPACE_NLA) { + return &TransConvertType_NLA; } - else if (t->spacetype == SPACE_SEQ) { + if (t->spacetype == SPACE_SEQ) { if (t->options & CTX_SEQUENCER_IMAGE) { - convert_type = TC_SEQ_IMAGE_DATA; - } - else { - convert_type = TC_SEQ_DATA; + return &TransConvertType_SequencerImage; } + return &TransConvertType_Sequencer; } - else if (t->spacetype == SPACE_GRAPH) { - convert_type = TC_GRAPH_EDIT_DATA; + if (t->spacetype == SPACE_GRAPH) { + return &TransConvertType_Graph; } - else if (t->spacetype == SPACE_NODE) { - convert_type = TC_NODE_DATA; + if (t->spacetype == SPACE_NODE) { + return &TransConvertType_Node; } - else if (t->spacetype == SPACE_CLIP) { + if (t->spacetype == SPACE_CLIP) { if (t->options & CTX_MOVIECLIP) { - convert_type = TC_TRACKING_DATA; + return &TransConvertType_Tracking; } - else if (t->options & CTX_MASK) { - convert_type = TC_MASKING_DATA; + if (t->options & CTX_MASK) { + return &TransConvertType_Mask; } + return NULL; } - else if (t->obedit_type != -1) { + if (t->obedit_type != -1) { if (t->obedit_type == OB_MESH) { if (t->mode == TFM_SKIN_RESIZE) { - convert_type = TC_MESH_SKIN; + return &TransConvertType_MeshSkin; } - else { - convert_type = TC_MESH_VERTS; + if (ELEM(t->mode, TFM_BWEIGHT, TFM_VERT_CREASE)) { + return &TransConvertType_MeshVertCData; } + return &TransConvertType_Mesh; } - else if (ELEM(t->obedit_type, OB_CURVES_LEGACY, OB_SURF)) { - convert_type = TC_CURVE_VERTS; + if (ELEM(t->obedit_type, OB_CURVES_LEGACY, OB_SURF)) { + return &TransConvertType_Curve; } - else if (t->obedit_type == OB_LATTICE) { - convert_type = TC_LATTICE_VERTS; + if (t->obedit_type == OB_LATTICE) { + return &TransConvertType_Lattice; } - else if (t->obedit_type == OB_MBALL) { - convert_type = TC_MBALL_VERTS; + if (t->obedit_type == OB_MBALL) { + return &TransConvertType_MBall; } - else if (t->obedit_type == OB_ARMATURE) { - convert_type = TC_ARMATURE_VERTS; + if (t->obedit_type == OB_ARMATURE) { + return &TransConvertType_EditArmature; } + return NULL; } - else if (ob && (ob->mode & OB_MODE_POSE)) { - convert_type = TC_POSE; + if (ob && (ob->mode & OB_MODE_POSE)) { + return &TransConvertType_Pose; } - else if (ob && (ob->mode & OB_MODE_ALL_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) { + if (ob && (ob->mode & OB_MODE_ALL_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) { Object *ob_armature = transform_object_deform_pose_armature_get(t, ob); if (ob_armature) { *r_obj_armature = ob_armature; - convert_type = TC_POSE; + return &TransConvertType_Pose; } + return NULL; } - else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && - PE_start_edit(PE_get_current(t->depsgraph, t->scene, ob))) { - convert_type = TC_PARTICLE_VERTS; + if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && + PE_start_edit(PE_get_current(t->depsgraph, t->scene, ob))) { + return &TransConvertType_Particle; } - else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) { + if (ob && (ob->mode & OB_MODE_ALL_PAINT)) { if ((t->options & CTX_PAINT_CURVE) && !ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) { - convert_type = TC_PAINT_CURVE_VERTS; + return &TransConvertType_PaintCurve; } + return NULL; } - else if ((ob) && (ELEM(ob->mode, - OB_MODE_PAINT_GPENCIL, - OB_MODE_SCULPT_GPENCIL, - OB_MODE_WEIGHT_GPENCIL, - OB_MODE_VERTEX_GPENCIL))) { + if ((ob) && (ELEM(ob->mode, + OB_MODE_PAINT_GPENCIL, + OB_MODE_SCULPT_GPENCIL, + OB_MODE_WEIGHT_GPENCIL, + OB_MODE_VERTEX_GPENCIL))) { /* In grease pencil all transformations must be canceled if not Object or Edit. */ + return NULL; } - else { - convert_type = TC_OBJECT; - } - - return convert_type; + return &TransConvertType_Object; } void createTransData(bContext *C, TransInfo *t) @@ -1376,133 +1132,64 @@ void createTransData(bContext *C, TransInfo *t) Object *ob_armature = NULL; t->data_type = convert_type_get(t, &ob_armature); - t->flag |= flags_from_data_type(t->data_type); + if (t->data_type == NULL) { + printf("edit type not implemented!\n"); + BLI_assert(t->data_len_all == -1); + t->data_len_all = 0; + return; + } + + t->flag |= t->data_type->flags; if (ob_armature) { init_TransDataContainers(t, ob_armature, &ob_armature, 1); } else { - ViewLayer *view_layer = t->view_layer; - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *ob = BKE_view_layer_active_object_get(t->view_layer); init_TransDataContainers(t, ob, NULL, 0); } - switch (t->data_type) { - case TC_ACTION_DATA: - createTransActionData(C, t); - break; - case TC_POSE: - t->options |= CTX_POSE_BONE; + if (t->data_type == &TransConvertType_Object) { + t->options |= CTX_OBJECT; - /* XXX active-layer checking isn't done - * as that should probably be checked through context instead. */ - createTransPose(t); - break; - case TC_ARMATURE_VERTS: - createTransArmatureVerts(t); - break; - case TC_CURSOR_IMAGE: - createTransCursor_image(t); - break; - case TC_CURSOR_SEQUENCER: - createTransCursor_sequencer(t); - break; - case TC_CURSOR_VIEW3D: - createTransCursor_view3d(t); - break; - case TC_CURVE_VERTS: - createTransCurveVerts(t); - break; - case TC_GRAPH_EDIT_DATA: - createTransGraphEditData(C, t); - break; - case TC_GPENCIL: - createTransGPencil(C, t); - break; - case TC_LATTICE_VERTS: - createTransLatticeVerts(t); - break; - case TC_MASKING_DATA: - createTransMaskingData(C, t); - break; - case TC_MBALL_VERTS: - createTransMBallVerts(t); - break; - case TC_MESH_VERTS: - createTransEditVerts(t); - break; - case TC_MESH_EDGES: - createTransEdge(t); - break; - case TC_MESH_SKIN: - createTransMeshSkin(t); - break; - case TC_MESH_UV: - createTransUVs(C, t); - break; - case TC_NLA_DATA: - createTransNlaData(C, t); - break; - case TC_NODE_DATA: - createTransNodeData(t); - break; - case TC_OBJECT: - t->options |= CTX_OBJECT; - - /* Needed for correct Object.obmat after duplication, see: T62135. */ - BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context)); - - if ((t->settings->transform_flag & SCE_XFORM_DATA_ORIGIN) != 0) { - t->options |= CTX_OBMODE_XFORM_OBDATA; - } - if ((t->settings->transform_flag & SCE_XFORM_SKIP_CHILDREN) != 0) { - t->options |= CTX_OBMODE_XFORM_SKIP_CHILDREN; - } - createTransObject(C, t); - /* Check if we're transforming the camera from the camera */ - if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { - View3D *v3d = t->view; - RegionView3D *rv3d = t->region->regiondata; - if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) { - /* we could have a flag to easily check an object is being transformed */ - if (v3d->camera->id.tag & LIB_TAG_DOIT) { - t->options |= CTX_CAMERA; - } - } - else if (v3d->ob_center && v3d->ob_center->id.tag & LIB_TAG_DOIT) { + /* Needed for correct Object.obmat after duplication, see: T62135. */ + BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context)); + + if ((t->settings->transform_flag & SCE_XFORM_DATA_ORIGIN) != 0) { + t->options |= CTX_OBMODE_XFORM_OBDATA; + } + if ((t->settings->transform_flag & SCE_XFORM_SKIP_CHILDREN) != 0) { + t->options |= CTX_OBMODE_XFORM_SKIP_CHILDREN; + } + TransConvertType_Object.createTransData(C, t); + /* Check if we're transforming the camera from the camera */ + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { + View3D *v3d = t->view; + RegionView3D *rv3d = t->region->regiondata; + if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) { + /* we could have a flag to easily check an object is being transformed */ + if (v3d->camera->id.tag & LIB_TAG_DOIT) { t->options |= CTX_CAMERA; } } - break; - case TC_OBJECT_TEXSPACE: - createTransTexspace(t); - break; - case TC_PAINT_CURVE_VERTS: - createTransPaintCurveVerts(C, t); - break; - case TC_PARTICLE_VERTS: - createTransParticleVerts(t); - break; - case TC_SCULPT: - createTransSculpt(C, t); - break; - case TC_SEQ_DATA: - t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point transform. */ - createTransSeqData(t); - break; - case TC_SEQ_IMAGE_DATA: + else if (v3d->ob_center && v3d->ob_center->id.tag & LIB_TAG_DOIT) { + t->options |= CTX_CAMERA; + } + } + } + else { + if (t->data_type == &TransConvertType_Pose) { + t->options |= CTX_POSE_BONE; + } + else if (t->data_type == &TransConvertType_Sequencer) { + /* Sequencer has no use for floating point transform. */ + t->num.flag |= NUM_NO_FRACTION; + } + else if (t->data_type == &TransConvertType_SequencerImage) { t->obedit_type = -1; - createTransSeqImageData(t); - break; - case TC_TRACKING_DATA: - createTransTrackingData(C, t); - break; - case TC_NONE: - default: - printf("edit type not implemented!\n"); - BLI_assert(t->data_len_all == -1); - t->data_len_all = 0; - return; + } + t->data_type->createTransData(C, t); } countAndCleanTransDataContainer(t); @@ -1706,89 +1393,10 @@ void transform_convert_flush_handle2D(TransData *td, TransData2D *td2d, const fl void recalcData(TransInfo *t) { - switch (t->data_type) { - case TC_ACTION_DATA: - recalcData_actedit(t); - break; - case TC_POSE: - recalcData_pose(t); - break; - case TC_ARMATURE_VERTS: - recalcData_edit_armature(t); - break; - case TC_CURVE_VERTS: - recalcData_curve(t); - break; - case TC_CURSOR_IMAGE: - recalcData_cursor_image(t); - break; - case TC_CURSOR_SEQUENCER: - recalcData_cursor_sequencer(t); - break; - case TC_CURSOR_VIEW3D: - recalcData_cursor_view3d(t); - break; - case TC_GRAPH_EDIT_DATA: - recalcData_graphedit(t); - break; - case TC_GPENCIL: - recalcData_gpencil_strokes(t); - break; - case TC_MASKING_DATA: - recalcData_mask_common(t); - break; - case TC_MESH_VERTS: - recalcData_mesh(t); - break; - case TC_MESH_EDGES: - recalcData_mesh_edge(t); - break; - case TC_MESH_SKIN: - recalcData_mesh_skin(t); - break; - case TC_MESH_UV: - recalcData_uv(t); - break; - case TC_NLA_DATA: - recalcData_nla(t); - break; - case TC_NODE_DATA: - flushTransNodes(t); - break; - case TC_OBJECT: - recalcData_objects(t); - break; - case TC_OBJECT_TEXSPACE: - recalcData_texspace(t); - break; - case TC_PAINT_CURVE_VERTS: - flushTransPaintCurve(t); - break; - case TC_SCULPT: - recalcData_sculpt(t); - break; - case TC_SEQ_DATA: - recalcData_sequencer(t); - break; - case TC_SEQ_IMAGE_DATA: - recalcData_sequencer_image(t); - break; - case TC_TRACKING_DATA: - recalcData_tracking(t); - break; - case TC_MBALL_VERTS: - recalcData_mball(t); - break; - case TC_LATTICE_VERTS: - recalcData_lattice(t); - break; - case TC_PARTICLE_VERTS: - recalcData_particles(t); - break; - case TC_NONE: - default: - break; + if (!t->data_type || !t->data_type->recalcData) { + return; } + t->data_type->recalcData(t); } /** \} */ diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h index 037fbe26c77..f32bff6dcff 100644 --- a/source/blender/editors/transform/transform_convert.h +++ b/source/blender/editors/transform/transform_convert.h @@ -21,6 +21,25 @@ struct TransDataCurveHandleFlags; struct TransInfo; struct bContext; +typedef struct TransConvertTypeInfo { + int flags; /* eTFlag */ + + /** + * Allocate and initialize `t->data`. + */ + void (*createTransData)(bContext *C, TransInfo *t); + + /** + * Force recalculation of data during transformation. + */ + void (*recalcData)(TransInfo *t); + + /** + * Called when the operation is finished. + */ + void (*special_aftertrans_update)(bContext *C, TransInfo *t); +} TransConvertTypeInfo; + /* transform_convert.c */ /** @@ -34,7 +53,6 @@ int special_transform_moving(TransInfo *t); void special_aftertrans_update(struct bContext *C, TransInfo *t); void sort_trans_data_dist(TransInfo *t); void createTransData(struct bContext *C, TransInfo *t); -bool clipUVTransform(TransInfo *t, float vec[2], bool resize); void clipUVData(TransInfo *t); void transform_convert_flush_handle2D(TransData *td, TransData2D *td2d, float y_fac); /** @@ -99,82 +117,53 @@ void animrecord_check_state(TransInfo *t, struct ID *id); /* transform_convert_action.c */ -void createTransActionData(bContext *C, TransInfo *t); -/* helper for recalcData() - for Action Editor transforms */ -void recalcData_actedit(TransInfo *t); -void special_aftertrans_update__actedit(bContext *C, TransInfo *t); +extern TransConvertTypeInfo TransConvertType_Action; /* transform_convert_armature.c */ +extern TransConvertTypeInfo TransConvertType_EditArmature; +extern TransConvertTypeInfo TransConvertType_Pose; + /** * Sets transform flags in the bones. * Returns total number of bones with #BONE_TRANSFORM. */ void transform_convert_pose_transflags_update(Object *ob, int mode, short around); -/** - * When objects array is NULL, use 't->data_container' as is. - */ -void createTransPose(TransInfo *t); -void createTransArmatureVerts(TransInfo *t); -void recalcData_edit_armature(TransInfo *t); -void recalcData_pose(TransInfo *t); -void special_aftertrans_update__pose(bContext *C, TransInfo *t); - /* transform_convert_cursor.c */ -void createTransCursor_image(TransInfo *t); -void createTransCursor_sequencer(TransInfo *t); -void createTransCursor_view3d(TransInfo *t); -void recalcData_cursor_image(TransInfo *t); -void recalcData_cursor_sequencer(TransInfo *t); -void recalcData_cursor_view3d(TransInfo *t); +extern TransConvertTypeInfo TransConvertType_CursorImage; +extern TransConvertTypeInfo TransConvertType_CursorSequencer; +extern TransConvertTypeInfo TransConvertType_Cursor3D; /* transform_convert_curve.c */ -void createTransCurveVerts(TransInfo *t); -void recalcData_curve(TransInfo *t); +extern TransConvertTypeInfo TransConvertType_Curve; /* transform_convert_graph.c */ -/** - * It is important to note that this doesn't always act on the selection (like it's usually done), - * it acts on a subset of it. E.g. the selection code may leave a hint that we just dragged on a - * left or right handle (SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT/RIGHT) and then we only transform the - * selected left or right handles accordingly. - * The points to be transformed are tagged with BEZT_FLAG_TEMP_TAG; some lower level curve - * functions may need to be made aware of this. It's ugly that these act based on selection state - * anyway. - */ -void createTransGraphEditData(bContext *C, TransInfo *t); -/* helper for recalcData() - for Graph Editor transforms */ -void recalcData_graphedit(TransInfo *t); -void special_aftertrans_update__graph(bContext *C, TransInfo *t); +extern TransConvertTypeInfo TransConvertType_Graph; /* transform_convert_gpencil.c */ -void createTransGPencil(bContext *C, TransInfo *t); -/* force recalculation of triangles during transformation */ -void recalcData_gpencil_strokes(TransInfo *t); +extern TransConvertTypeInfo TransConvertType_GPencil; /* transform_convert_lattice.c */ -void createTransLatticeVerts(TransInfo *t); -void recalcData_lattice(TransInfo *t); +extern TransConvertTypeInfo TransConvertType_Lattice; /* transform_convert_mask.c */ -void createTransMaskingData(bContext *C, TransInfo *t); -void recalcData_mask_common(TransInfo *t); -void special_aftertrans_update__mask(bContext *C, TransInfo *t); +extern TransConvertTypeInfo TransConvertType_Mask; /* transform_convert_mball.c */ -void createTransMBallVerts(TransInfo *t); -void recalcData_mball(TransInfo *t); +extern TransConvertTypeInfo TransConvertType_MBall; /* transform_convert_mesh.c */ +extern TransConvertTypeInfo TransConvertType_Mesh; + struct TransIslandData { float (*center)[3]; float (*axismtx)[3][3]; @@ -233,84 +222,60 @@ void transform_convert_mesh_crazyspace_transdata_set(const float mtx[3][3], struct TransData *r_td); void transform_convert_mesh_crazyspace_free(struct TransMeshDataCrazySpace *r_crazyspace_data); -void createTransEditVerts(TransInfo *t); -void recalcData_mesh(TransInfo *t); void special_aftertrans_update__mesh(bContext *C, TransInfo *t); /* transform_convert_mesh_edge.c */ -void createTransEdge(TransInfo *t); -void recalcData_mesh_edge(TransInfo *t); +extern TransConvertTypeInfo TransConvertType_MeshEdge; /* transform_convert_mesh_skin.c */ -void createTransMeshSkin(TransInfo *t); -void recalcData_mesh_skin(TransInfo *t); +extern TransConvertTypeInfo TransConvertType_MeshSkin; /* transform_convert_mesh_uv.c */ -void createTransUVs(bContext *C, TransInfo *t); -/* helper for recalcData() - for Image Editor transforms */ -void recalcData_uv(TransInfo *t); +extern TransConvertTypeInfo TransConvertType_MeshUV; + +/* transform_convert_mesh_vert_cdata.c */ + +extern TransConvertTypeInfo TransConvertType_MeshVertCData; /* transform_convert_nla.c */ -void createTransNlaData(bContext *C, TransInfo *t); -/* helper for recalcData() - for NLA Editor transforms */ -void recalcData_nla(TransInfo *t); -void special_aftertrans_update__nla(bContext *C, TransInfo *t); +extern TransConvertTypeInfo TransConvertType_NLA; /* transform_convert_node.c */ -void createTransNodeData(TransInfo *t); -void flushTransNodes(TransInfo *t); -void special_aftertrans_update__node(bContext *C, TransInfo *t); +extern TransConvertTypeInfo TransConvertType_Node; /* transform_convert_object.c */ -void createTransObject(bContext *C, TransInfo *t); -/* helper for recalcData() - for object transforms, typically in the 3D view */ -void recalcData_objects(TransInfo *t); -void special_aftertrans_update__object(bContext *C, TransInfo *t); +extern TransConvertTypeInfo TransConvertType_Object; /* transform_convert_object_texspace.c */ -void createTransTexspace(TransInfo *t); -/* helper for recalcData() - for object transforms, typically in the 3D view */ -void recalcData_texspace(TransInfo *t); +extern TransConvertTypeInfo TransConvertType_ObjectTexSpace; /* transform_convert_paintcurve.c */ -void createTransPaintCurveVerts(bContext *C, TransInfo *t); -void flushTransPaintCurve(TransInfo *t); +extern TransConvertTypeInfo TransConvertType_PaintCurve; /* transform_convert_particle.c */ -void createTransParticleVerts(TransInfo *t); -void recalcData_particles(TransInfo *t); +extern TransConvertTypeInfo TransConvertType_Particle; /* transform_convert_sculpt.c */ -void createTransSculpt(bContext *C, TransInfo *t); -void recalcData_sculpt(TransInfo *t); -void special_aftertrans_update__sculpt(bContext *C, TransInfo *t); +extern TransConvertTypeInfo TransConvertType_Sculpt; /* transform_convert_sequencer.c */ -void createTransSeqData(TransInfo *t); -/* helper for recalcData() - for sequencer transforms */ -void recalcData_sequencer(TransInfo *t); -void special_aftertrans_update__sequencer(bContext *C, TransInfo *t); +extern TransConvertTypeInfo TransConvertType_Sequencer; /* transform_convert_sequencer_image.c */ -void createTransSeqImageData(TransInfo *t); -void recalcData_sequencer_image(TransInfo *t); -void special_aftertrans_update__sequencer_image(bContext *C, TransInfo *t); +extern TransConvertTypeInfo TransConvertType_SequencerImage; /* transform_convert_tracking.c */ -void createTransTrackingData(bContext *C, TransInfo *t); -/* helper for recalcData() - for Movie Clip transforms */ -void recalcData_tracking(TransInfo *t); -void special_aftertrans_update__movieclip(bContext *C, TransInfo *t); +extern TransConvertTypeInfo TransConvertType_Tracking; diff --git a/source/blender/editors/transform/transform_convert_action.c b/source/blender/editors/transform/transform_convert_action.c index 71c245cd512..8c6f2baf84a 100644 --- a/source/blender/editors/transform/transform_convert_action.c +++ b/source/blender/editors/transform/transform_convert_action.c @@ -18,6 +18,7 @@ #include "BKE_context.h" #include "BKE_gpencil.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_mask.h" #include "BKE_nla.h" @@ -289,7 +290,7 @@ static int MaskLayerToTransData(TransData *td, return count; } -void createTransActionData(bContext *C, TransInfo *t) +static void createTransActionData(bContext *C, TransInfo *t) { Scene *scene = t->scene; TransData *td = NULL; @@ -311,6 +312,7 @@ void createTransActionData(bContext *C, TransInfo *t) const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; int count = 0; + int gpf_count = 0; float cfra; float ypos = 1.0f / ((ysize / xsize) * (xmask / ymask)) * BLI_rctf_cent_y(&t->region->v2d.cur); @@ -320,17 +322,12 @@ void createTransActionData(bContext *C, TransInfo *t) } /* filter data */ - if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) { - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT); - } - else { - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/); - } + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); /* which side of the current frame should be allowed */ if (t->mode == TFM_TIME_EXTEND) { - t->frame_side = transform_convert_frame_side_dir_get(t, (float)CFRA); + t->frame_side = transform_convert_frame_side_dir_get(t, (float)scene->r.cfra); } else { /* normal transform - both sides of current frame are considered */ @@ -345,10 +342,10 @@ void createTransActionData(bContext *C, TransInfo *t) * higher scaling ratios, but is faster than converting all points) */ if (adt) { - cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); + cfra = BKE_nla_tweakedit_remap(adt, (float)scene->r.cfra, NLATIME_CONVERT_UNMAP); } else { - cfra = (float)CFRA; + cfra = (float)scene->r.cfra; } if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) { @@ -365,13 +362,16 @@ void createTransActionData(bContext *C, TransInfo *t) } if (adt_count > 0) { + if (ELEM(ale->type, ANIMTYPE_GPLAYER, ANIMTYPE_MASKLAYER)) { + gpf_count += adt_count; + } count += adt_count; ale->tag = true; } } /* stop if trying to build list if nothing selected */ - if (count == 0) { + if (count == 0 && gpf_count == 0) { /* cleanup temp list */ ANIM_animdata_freelist(&anim_data); return; @@ -387,8 +387,9 @@ void createTransActionData(bContext *C, TransInfo *t) td = tc->data; td2d = tc->data_2d; - if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) { - tc->custom.type.data = tfd = MEM_callocN(sizeof(tGPFtransdata) * count, "tGPFtransdata"); + if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK, ANIMCONT_DOPESHEET, ANIMCONT_TIMELINE)) { + tc->data_gpf_len = gpf_count; + tc->custom.type.data = tfd = MEM_callocN(sizeof(tGPFtransdata) * gpf_count, "tGPFtransdata"); tc->custom.type.use_free = true; } @@ -399,7 +400,7 @@ void createTransActionData(bContext *C, TransInfo *t) continue; } - cfra = (float)CFRA; + cfra = (float)scene->r.cfra; { AnimData *adt; @@ -447,10 +448,10 @@ void createTransActionData(bContext *C, TransInfo *t) adt = ANIM_nla_mapping_get(&ac, ale); if (adt) { - cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); + cfra = BKE_nla_tweakedit_remap(adt, (float)scene->r.cfra, NLATIME_CONVERT_UNMAP); } else { - cfra = (float)CFRA; + cfra = (float)scene->r.cfra; } if (ale->type == ANIMTYPE_GPLAYER) { @@ -558,13 +559,14 @@ static void flushTransIntFrameActionData(TransInfo *t) TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); tGPFtransdata *tfd = tc->custom.type.data; - /* flush data! */ - for (int i = 0; i < tc->data_len; i++, tfd++) { + /* flush data! + * Expects data_gpf_len to be set in the data container. */ + for (int i = 0; i < tc->data_gpf_len; i++, tfd++) { *(tfd->sdata) = round_fl_to_int(tfd->val); } } -void recalcData_actedit(TransInfo *t) +static void recalcData_actedit(TransInfo *t) { ViewLayer *view_layer = t->view_layer; SpaceAction *saction = (SpaceAction *)t->area->spacedata.first; @@ -574,12 +576,14 @@ void recalcData_actedit(TransInfo *t) bAnimListElem *ale; int filter; + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + /* initialize relevant anim-context 'context' data from TransInfo data */ /* NOTE: sync this with the code in ANIM_animdata_get_context() */ ac.bmain = CTX_data_main(t->context); ac.scene = t->scene; ac.view_layer = t->view_layer; - ac.obact = OBACT(view_layer); + ac.obact = BKE_view_layer_active_object_get(view_layer); ac.area = t->area; ac.region = t->region; ac.sl = (t->area) ? t->area->spacedata.first : NULL; @@ -589,7 +593,7 @@ void recalcData_actedit(TransInfo *t) ANIM_animdata_context_getdata(&ac); /* perform flush */ - if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) { + if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK, ANIMCONT_DOPESHEET, ANIMCONT_TIMELINE)) { /* flush transform values back to actual coordinates */ flushTransIntFrameActionData(t); } @@ -735,7 +739,7 @@ static void posttrans_action_clean(bAnimContext *ac, bAction *act) int filter; /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/); + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_FCURVESONLY); ANIM_animdata_filter(ac, &anim_data, filter, act, ANIMCONT_ACTION); /* loop through relevant data, removing keyframes as appropriate @@ -758,7 +762,7 @@ static void posttrans_action_clean(bAnimContext *ac, bAction *act) ANIM_animdata_freelist(&anim_data); } -void special_aftertrans_update__actedit(bContext *C, TransInfo *t) +static void special_aftertrans_update__actedit(bContext *C, TransInfo *t) { SpaceAction *saction = (SpaceAction *)t->area->spacedata.first; bAnimContext ac; @@ -776,32 +780,44 @@ void special_aftertrans_update__actedit(bContext *C, TransInfo *t) if (ELEM(ac.datatype, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY, ANIMCONT_TIMELINE)) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; - short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/); + short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT); /* get channels to work on */ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - /* these should all be F-Curves */ for (ale = anim_data.first; ale; ale = ale->next) { - AnimData *adt = ANIM_nla_mapping_get(&ac, ale); - FCurve *fcu = (FCurve *)ale->key_data; - - /* 3 cases here for curve cleanups: - * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done - * 2) canceled == 0 -> user confirmed the transform, - * so duplicates should be removed - * 3) canceled + duplicate -> user canceled the transform, - * but we made duplicates, so get rid of these - */ - if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) { - if (adt) { - ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0); - posttrans_fcurve_clean(fcu, SELECT, false); /* only use handles in graph editor */ - ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0); - } - else { - posttrans_fcurve_clean(fcu, SELECT, false); /* only use handles in graph editor */ + switch (ale->datatype) { + case ALE_GPFRAME: + ale->id->tag &= ~LIB_TAG_DOIT; + posttrans_gpd_clean((bGPdata *)ale->id); + break; + + case ALE_FCURVE: { + AnimData *adt = ANIM_nla_mapping_get(&ac, ale); + FCurve *fcu = (FCurve *)ale->key_data; + + /* 3 cases here for curve cleanups: + * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done + * 2) canceled == 0 -> user confirmed the transform, + * so duplicates should be removed + * 3) canceled + duplicate -> user canceled the transform, + * but we made duplicates, so get rid of these + */ + if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) { + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0); + posttrans_fcurve_clean(fcu, SELECT, false); /* only use handles in graph editor */ + ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0); + } + else { + posttrans_fcurve_clean(fcu, SELECT, false); /* only use handles in graph editor */ + } + } + break; } + + default: + BLI_assert_msg(false, "Keys cannot be transformed into this animation type."); } } @@ -847,15 +863,8 @@ void special_aftertrans_update__actedit(bContext *C, TransInfo *t) LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) { if (ale->datatype == ALE_GPFRAME) { - ale->id->tag |= LIB_TAG_DOIT; - } - } - LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) { - if (ale->datatype == ALE_GPFRAME) { - if (ale->id->tag & LIB_TAG_DOIT) { - ale->id->tag &= ~LIB_TAG_DOIT; - posttrans_gpd_clean((bGPdata *)ale->id); - } + ale->id->tag &= ~LIB_TAG_DOIT; + posttrans_gpd_clean((bGPdata *)ale->id); } } ANIM_animdata_freelist(&anim_data); @@ -878,15 +887,8 @@ void special_aftertrans_update__actedit(bContext *C, TransInfo *t) LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) { if (ale->datatype == ALE_MASKLAY) { - ale->id->tag |= LIB_TAG_DOIT; - } - } - LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) { - if (ale->datatype == ALE_MASKLAY) { - if (ale->id->tag & LIB_TAG_DOIT) { - ale->id->tag &= ~LIB_TAG_DOIT; - posttrans_mask_clean((Mask *)ale->id); - } + ale->id->tag &= ~LIB_TAG_DOIT; + posttrans_mask_clean((Mask *)ale->id); } } ANIM_animdata_freelist(&anim_data); @@ -902,18 +904,18 @@ void special_aftertrans_update__actedit(bContext *C, TransInfo *t) if (ELEM(t->frame_side, 'L', 'R')) { /* TFM_TIME_EXTEND */ /* same as below */ ED_markers_post_apply_transform( - ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side); + ED_context_get_markers(C), t->scene, t->mode, t->values_final[0], t->frame_side); } else /* TFM_TIME_TRANSLATE */ #endif { ED_markers_post_apply_transform( - ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side); + ED_context_get_markers(C), t->scene, t->mode, t->values_final[0], t->frame_side); } } else if (t->mode == TFM_TIME_SCALE) { ED_markers_post_apply_transform( - ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side); + ED_context_get_markers(C), t->scene, t->mode, t->values_final[0], t->frame_side); } } @@ -927,3 +929,10 @@ void special_aftertrans_update__actedit(bContext *C, TransInfo *t) } /** \} */ + +TransConvertTypeInfo TransConvertType_Action = { + /* flags */ (T_POINTS | T_2D_EDIT), + /* createTransData */ createTransActionData, + /* recalcData */ recalcData_actedit, + /* special_aftertrans_update */ special_aftertrans_update__actedit, +}; diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index e1b25acb21e..d83cca15219 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -93,8 +93,8 @@ static void autokeyframe_pose( KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene); ListBase nla_cache = {NULL, NULL}; Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); - const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, - (float)CFRA); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( + depsgraph, (float)scene->r.cfra); eInsertKeyFlags flag = 0; /* flag is initialized from UserPref keyframing settings @@ -701,7 +701,7 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr td->con = pchan->constraints.first; } -void createTransPose(TransInfo *t) +static void createTransPose(bContext *UNUSED(C), TransInfo *t) { Main *bmain = CTX_data_main(t->context); @@ -879,7 +879,7 @@ void createTransPose(TransInfo *t) } } -void createTransArmatureVerts(TransInfo *t) +static void createTransArmatureVerts(bContext *UNUSED(C), TransInfo *t) { t->data_len_all = 0; @@ -1189,10 +1189,10 @@ static void restoreBones(TransDataContainer *tc) } } -void recalcData_edit_armature(TransInfo *t) +static void recalcData_edit_armature(TransInfo *t) { if (t->state != TRANS_CANCEL) { - applyProject(t); + applySnappingIndividual(t); } FOREACH_TRANS_DATA_CONTAINER (t, tc) { @@ -1356,7 +1356,7 @@ static void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, O } mul_v3_m4v3(data->grabtarget, flip_mtx, td->loc); if (pid) { - /* TODO(germano): Relative Mirror support. */ + /* TODO(@germano): Relative Mirror support. */ } data->flag |= CONSTRAINT_IK_AUTO; /* Add a temporary auto IK constraint here, as we will only temporarily active this @@ -1412,7 +1412,7 @@ static void restoreMirrorPoseBones(TransDataContainer *tc) } } -void recalcData_pose(TransInfo *t) +static void recalcData_pose(TransInfo *t) { if (t->mode == TFM_BONESIZE) { /* Handle the exception where for TFM_BONESIZE in edit mode we pretend to be @@ -1684,7 +1684,7 @@ static void pose_grab_with_ik_clear(Main *bmain, Object *ob) } } -void special_aftertrans_update__pose(bContext *C, TransInfo *t) +static void special_aftertrans_update__pose(bContext *C, TransInfo *t) { Object *ob; @@ -1768,3 +1768,17 @@ void special_aftertrans_update__pose(bContext *C, TransInfo *t) } /** \} */ + +TransConvertTypeInfo TransConvertType_EditArmature = { + /* flags */ (T_EDIT | T_POINTS), + /* createTransData */ createTransArmatureVerts, + /* recalcData */ recalcData_edit_armature, + /* special_aftertrans_update */ NULL, +}; + +TransConvertTypeInfo TransConvertType_Pose = { + /* flags */ 0, + /* createTransData */ createTransPose, + /* recalcData */ recalcData_pose, + /* special_aftertrans_update */ special_aftertrans_update__pose, +}; diff --git a/source/blender/editors/transform/transform_convert_cursor.c b/source/blender/editors/transform/transform_convert_cursor.c index 5e6eee192f2..0bf6f06a9f2 100644 --- a/source/blender/editors/transform/transform_convert_cursor.c +++ b/source/blender/editors/transform/transform_convert_cursor.c @@ -82,13 +82,13 @@ static void recalcData_cursor_2D_impl(TransInfo *t) /** \name Image Cursor * \{ */ -void createTransCursor_image(TransInfo *t) +static void createTransCursor_image(bContext *UNUSED(C), TransInfo *t) { SpaceImage *sima = t->area->spacedata.first; createTransCursor_2D_impl(t, sima->cursor); } -void recalcData_cursor_image(TransInfo *t) +static void recalcData_cursor_image(TransInfo *t) { recalcData_cursor_2D_impl(t); } @@ -99,7 +99,7 @@ void recalcData_cursor_image(TransInfo *t) /** \name Sequencer Cursor * \{ */ -void createTransCursor_sequencer(TransInfo *t) +static void createTransCursor_sequencer(bContext *UNUSED(C), TransInfo *t) { SpaceSeq *sseq = t->area->spacedata.first; if (sseq->mainb != SEQ_DRAW_IMG_IMBUF) { @@ -108,7 +108,7 @@ void createTransCursor_sequencer(TransInfo *t) createTransCursor_2D_impl(t, sseq->cursor); } -void recalcData_cursor_sequencer(TransInfo *t) +static void recalcData_cursor_sequencer(TransInfo *t) { recalcData_cursor_2D_impl(t); } @@ -119,7 +119,7 @@ void recalcData_cursor_sequencer(TransInfo *t) /** \name View 3D Cursor * \{ */ -void createTransCursor_view3d(TransInfo *t) +static void createTransCursor_view3d(bContext *UNUSED(C), TransInfo *t) { TransData *td; @@ -178,9 +178,30 @@ void createTransCursor_view3d(TransInfo *t) td->ext->rotOrder = cursor->rotation_mode; } -void recalcData_cursor_view3d(TransInfo *t) +static void recalcData_cursor_view3d(TransInfo *t) { DEG_id_tag_update(&t->scene->id, ID_RECALC_COPY_ON_WRITE); } /** \} */ + +TransConvertTypeInfo TransConvertType_CursorImage = { + /* flags */ T_2D_EDIT, + /* createTransData */ createTransCursor_image, + /* recalcData */ recalcData_cursor_image, + /* special_aftertrans_update */ NULL, +}; + +TransConvertTypeInfo TransConvertType_CursorSequencer = { + /* flags */ T_2D_EDIT, + /* createTransData */ createTransCursor_sequencer, + /* recalcData */ recalcData_cursor_sequencer, + /* special_aftertrans_update */ NULL, +}; + +TransConvertTypeInfo TransConvertType_Cursor3D = { + /* flags */ 0, + /* createTransData */ createTransCursor_view3d, + /* recalcData */ recalcData_cursor_view3d, + /* special_aftertrans_update */ NULL, +}; diff --git a/source/blender/editors/transform/transform_convert_curve.c b/source/blender/editors/transform/transform_convert_curve.c index 51acfb2a788..404b1293208 100644 --- a/source/blender/editors/transform/transform_convert_curve.c +++ b/source/blender/editors/transform/transform_convert_curve.c @@ -62,7 +62,7 @@ static int bezt_select_to_transform_triple_flag(const BezTriple *bezt, const boo return flag; } -void createTransCurveVerts(TransInfo *t) +static void createTransCurveVerts(bContext *UNUSED(C), TransInfo *t) { #define SEL_F1 (1 << 0) @@ -415,10 +415,10 @@ void createTransCurveVerts(TransInfo *t) #undef SEL_F3 } -void recalcData_curve(TransInfo *t) +static void recalcData_curve(TransInfo *t) { if (t->state != TRANS_CANCEL) { - applyProject(t); + applySnappingIndividual(t); } FOREACH_TRANS_DATA_CONTAINER (t, tc) { @@ -446,3 +446,10 @@ void recalcData_curve(TransInfo *t) } /** \} */ + +TransConvertTypeInfo TransConvertType_Curve = { + /* flags */ (T_EDIT | T_POINTS), + /* createTransData */ createTransCurveVerts, + /* recalcData */ recalcData_curve, + /* special_aftertrans_update */ NULL, +}; diff --git a/source/blender/editors/transform/transform_convert_gpencil.c b/source/blender/editors/transform/transform_convert_gpencil.c index a88d42b7f30..b3d58f25ad3 100644 --- a/source/blender/editors/transform/transform_convert_gpencil.c +++ b/source/blender/editors/transform/transform_convert_gpencil.c @@ -19,6 +19,7 @@ #include "BKE_gpencil.h" #include "BKE_gpencil_curve.h" #include "BKE_gpencil_geom.h" +#include "BKE_layer.h" #include "ED_gpencil.h" #include "ED_keyframing.h" @@ -672,7 +673,7 @@ static void createTransGPencil_strokes(bContext *C, } } -void createTransGPencil(bContext *C, TransInfo *t) +static void createTransGPencil(bContext *C, TransInfo *t) { if (t->data_container_len == 0) { return; @@ -681,11 +682,12 @@ void createTransGPencil(bContext *C, TransInfo *t) Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); const Scene *scene = CTX_data_scene(C); ToolSettings *ts = scene->toolsettings; - Object *obact = OBACT(t->view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *obact = BKE_view_layer_active_object_get(t->view_layer); bGPdata *gpd = obact->data; BLI_assert(gpd != NULL); - const int cfra_scene = CFRA; + const int cfra_scene = scene->r.cfra; const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); const bool use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) != @@ -737,7 +739,7 @@ void createTransGPencil(bContext *C, TransInfo *t) } } -void recalcData_gpencil_strokes(TransInfo *t) +static void recalcData_gpencil_strokes(TransInfo *t) { TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); GHash *strokes = BLI_ghash_ptr_new(__func__); @@ -762,3 +764,10 @@ void recalcData_gpencil_strokes(TransInfo *t) } /** \} */ + +TransConvertTypeInfo TransConvertType_GPencil = { + /* flags */ (T_EDIT | T_POINTS), + /* createTransData */ createTransGPencil, + /* recalcData */ recalcData_gpencil_strokes, + /* special_aftertrans_update */ NULL, +}; diff --git a/source/blender/editors/transform/transform_convert_graph.c b/source/blender/editors/transform/transform_convert_graph.c index 2039daee386..4bcbce8bc83 100644 --- a/source/blender/editors/transform/transform_convert_graph.c +++ b/source/blender/editors/transform/transform_convert_graph.c @@ -14,6 +14,7 @@ #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_layer.h" #include "BKE_nla.h" #include "BKE_report.h" @@ -199,7 +200,16 @@ static void graph_key_shortest_dist( } } -void createTransGraphEditData(bContext *C, TransInfo *t) +/** + * It is important to note that this doesn't always act on the selection (like it's usually done), + * it acts on a subset of it. E.g. the selection code may leave a hint that we just dragged on a + * left or right handle (SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT/RIGHT) and then we only transform the + * selected left or right handles accordingly. + * The points to be transformed are tagged with BEZT_FLAG_TEMP_TAG; some lower level curve + * functions may need to be made aware of this. It's ugly that these act based on selection state + * anyway. + */ +static void createTransGraphEditData(bContext *C, TransInfo *t) { SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first; Scene *scene = t->scene; @@ -232,13 +242,14 @@ void createTransGraphEditData(bContext *C, TransInfo *t) anim_map_flag |= ANIM_get_normalization_flags(&ac); /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE); + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE | + ANIMFILTER_FCURVESONLY); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); /* 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) { - t->frame_side = transform_convert_frame_side_dir_get(t, (float)CFRA); + t->frame_side = transform_convert_frame_side_dir_get(t, (float)scene->r.cfra); } else { /* normal transform - both sides of current frame are considered */ @@ -263,10 +274,10 @@ void createTransGraphEditData(bContext *C, TransInfo *t) * higher scaling ratios, but is faster than converting all points) */ if (adt) { - cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); + cfra = BKE_nla_tweakedit_remap(adt, (float)scene->r.cfra, NLATIME_CONVERT_UNMAP); } else { - cfra = (float)CFRA; + cfra = (float)scene->r.cfra; } for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { @@ -369,10 +380,10 @@ void createTransGraphEditData(bContext *C, TransInfo *t) * higher scaling ratios, but is faster than converting all points) */ if (adt) { - cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); + cfra = BKE_nla_tweakedit_remap(adt, (float)scene->r.cfra, NLATIME_CONVERT_UNMAP); } else { - cfra = (float)CFRA; + cfra = (float)scene->r.cfra; } unit_scale = ANIM_unit_mapping_get_factor( @@ -560,10 +571,10 @@ void createTransGraphEditData(bContext *C, TransInfo *t) * higher scaling ratios, but is faster than converting all points) */ if (adt) { - cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); + cfra = BKE_nla_tweakedit_remap(adt, (float)scene->r.cfra, NLATIME_CONVERT_UNMAP); } else { - cfra = (float)CFRA; + cfra = (float)scene->r.cfra; } for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { @@ -885,7 +896,7 @@ static void remake_graph_transdata(TransInfo *t, ListBase *anim_data) } } -void recalcData_graphedit(TransInfo *t) +static void recalcData_graphedit(TransInfo *t) { SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first; ViewLayer *view_layer = t->view_layer; @@ -897,12 +908,14 @@ void recalcData_graphedit(TransInfo *t) bAnimListElem *ale; int dosort = 0; + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + /* initialize relevant anim-context 'context' data from TransInfo data */ /* NOTE: sync this with the code in ANIM_animdata_get_context() */ ac.bmain = CTX_data_main(t->context); ac.scene = t->scene; ac.view_layer = t->view_layer; - ac.obact = OBACT(view_layer); + ac.obact = BKE_view_layer_active_object_get(view_layer); ac.area = t->area; ac.region = t->region; ac.sl = (t->area) ? t->area->spacedata.first : NULL; @@ -915,7 +928,8 @@ void recalcData_graphedit(TransInfo *t) flushTransGraphData(t); /* get curves to check if a re-sort is needed */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE); + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE | + ANIMFILTER_FCURVESONLY); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); /* now test if there is a need to re-sort */ @@ -932,7 +946,7 @@ void recalcData_graphedit(TransInfo *t) dosort++; } else { - calchandles_fcurve_ex(fcu, BEZT_FLAG_TEMP_TAG); + BKE_fcurve_handles_recalc_ex(fcu, BEZT_FLAG_TEMP_TAG); } /* set refresh tags for objects using this animation, @@ -958,7 +972,7 @@ void recalcData_graphedit(TransInfo *t) /** \name Special After Transform Graph * \{ */ -void special_aftertrans_update__graph(bContext *C, TransInfo *t) +static void special_aftertrans_update__graph(bContext *C, TransInfo *t) { SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first; bAnimContext ac; @@ -975,7 +989,8 @@ void special_aftertrans_update__graph(bContext *C, TransInfo *t) if (ac.datatype) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; - short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE); + short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE | + ANIMFILTER_FCURVESONLY); /* get channels to work on */ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); @@ -1018,3 +1033,10 @@ void special_aftertrans_update__graph(bContext *C, TransInfo *t) } /** \} */ + +TransConvertTypeInfo TransConvertType_Graph = { + /* flags */ (T_POINTS | T_2D_EDIT), + /* createTransData */ createTransGraphEditData, + /* recalcData */ recalcData_graphedit, + /* special_aftertrans_update */ special_aftertrans_update__graph, +}; diff --git a/source/blender/editors/transform/transform_convert_lattice.c b/source/blender/editors/transform/transform_convert_lattice.c index f02d4e94448..b77538dc249 100644 --- a/source/blender/editors/transform/transform_convert_lattice.c +++ b/source/blender/editors/transform/transform_convert_lattice.c @@ -25,7 +25,7 @@ /** \name Curve/Surfaces Transform Creation * \{ */ -void createTransLatticeVerts(TransInfo *t) +static void createTransLatticeVerts(bContext *UNUSED(C), TransInfo *t) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { @@ -98,10 +98,10 @@ void createTransLatticeVerts(TransInfo *t) } } -void recalcData_lattice(TransInfo *t) +static void recalcData_lattice(TransInfo *t) { if (t->state != TRANS_CANCEL) { - applyProject(t); + applySnappingIndividual(t); } FOREACH_TRANS_DATA_CONTAINER (t, tc) { @@ -114,3 +114,10 @@ void recalcData_lattice(TransInfo *t) } /** \} */ + +TransConvertTypeInfo TransConvertType_Lattice = { + /* flags */ (T_EDIT | T_POINTS), + /* createTransData */ createTransLatticeVerts, + /* recalcData */ recalcData_lattice, + /* special_aftertrans_update */ NULL, +}; diff --git a/source/blender/editors/transform/transform_convert_mask.c b/source/blender/editors/transform/transform_convert_mask.c index 5255cc4412e..2dca59a5da1 100644 --- a/source/blender/editors/transform/transform_convert_mask.c +++ b/source/blender/editors/transform/transform_convert_mask.c @@ -117,7 +117,7 @@ static void MaskPointToTransData(Scene *scene, const bool is_sel_any = MASKPOINT_ISSEL_ANY(point); float parent_matrix[3][3], parent_inverse_matrix[3][3]; - BKE_mask_point_parent_matrix_get(point, CFRA, parent_matrix); + BKE_mask_point_parent_matrix_get(point, scene->r.cfra, parent_matrix); invert_m3_m3(parent_inverse_matrix, parent_matrix); if (is_prop_edit || is_sel_point) { @@ -245,7 +245,7 @@ static void MaskPointToTransData(Scene *scene, } } -void createTransMaskingData(bContext *C, TransInfo *t) +static void createTransMaskingData(bContext *C, TransInfo *t) { Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); @@ -261,18 +261,10 @@ void createTransMaskingData(bContext *C, TransInfo *t) tc->data_len = 0; - if (!mask) { + if (!ED_maskedit_mask_visible_splines_poll(C)) { return; } - if (t->spacetype == SPACE_CLIP) { - SpaceClip *sc = t->area->spacedata.first; - MovieClip *clip = ED_space_clip_get_clip(sc); - if (!clip) { - return; - } - } - /* count */ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; @@ -424,7 +416,7 @@ static void flushTransMasking(TransInfo *t) } } -void recalcData_mask_common(TransInfo *t) +static void recalcData_mask_common(TransInfo *t) { Mask *mask = CTX_data_edit_mask(t->context); @@ -439,7 +431,7 @@ void recalcData_mask_common(TransInfo *t) /** \name Special After Transform Mask * \{ */ -void special_aftertrans_update__mask(bContext *C, TransInfo *t) +static void special_aftertrans_update__mask(bContext *C, TransInfo *t) { Mask *mask = NULL; @@ -463,7 +455,7 @@ void special_aftertrans_update__mask(bContext *C, TransInfo *t) if (IS_AUTOKEY_ON(t->scene)) { Scene *scene = t->scene; - if (ED_mask_layer_shape_auto_key_select(mask, CFRA)) { + if (ED_mask_layer_shape_auto_key_select(mask, scene->r.cfra)) { WM_event_add_notifier(C, NC_MASK | ND_DATA, &mask->id); DEG_id_tag_update(&mask->id, 0); } @@ -471,3 +463,10 @@ void special_aftertrans_update__mask(bContext *C, TransInfo *t) } /** \} */ + +TransConvertTypeInfo TransConvertType_Mask = { + /* flags */ (T_POINTS | T_2D_EDIT), + /* createTransData */ createTransMaskingData, + /* recalcData */ recalcData_mask_common, + /* special_aftertrans_update */ special_aftertrans_update__mask, +}; diff --git a/source/blender/editors/transform/transform_convert_mball.c b/source/blender/editors/transform/transform_convert_mball.c index 7cba4f97886..7ae93524d0b 100644 --- a/source/blender/editors/transform/transform_convert_mball.c +++ b/source/blender/editors/transform/transform_convert_mball.c @@ -22,7 +22,7 @@ /** \name Meta Elements Transform Creation * \{ */ -void createTransMBallVerts(TransInfo *t) +static void createTransMBallVerts(bContext *UNUSED(C), TransInfo *t) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { MetaBall *mb = (MetaBall *)tc->obedit->data; @@ -119,10 +119,10 @@ void createTransMBallVerts(TransInfo *t) /** \name Recalc Meta Ball * \{ */ -void recalcData_mball(TransInfo *t) +static void recalcData_mball(TransInfo *t) { if (t->state != TRANS_CANCEL) { - applyProject(t); + applySnappingIndividual(t); } FOREACH_TRANS_DATA_CONTAINER (t, tc) { if (tc->data_len) { @@ -132,3 +132,10 @@ void recalcData_mball(TransInfo *t) } /** \} */ + +TransConvertTypeInfo TransConvertType_MBall = { + /* flags */ (T_EDIT | T_POINTS), + /* createTransData */ createTransMBallVerts, + /* recalcData */ recalcData_mball, + /* special_aftertrans_update */ NULL, +}; diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index d4b12142162..f67a44703e5 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -1314,7 +1314,8 @@ void transform_convert_mesh_crazyspace_detect(TransInfo *t, * correction with \a quats, relative to the coordinates after * the modifiers that support deform matrices \a defcos. */ -#if 0 /* TODO(campbell): fix crazy-space & extrude so it can be enabled for general use. */ +#if 0 /* TODO(@campbellbarton): fix crazy-space & extrude so it can be enabled for general use. \ + */ if ((totleft > 0) || (totleft == -1)) #else if (totleft > 0) @@ -1408,7 +1409,6 @@ static void VertsToTransData(TransInfo *t, TransDataExtension *tx, BMEditMesh *em, BMVert *eve, - float *bweight, const struct TransIslandData *island_data, const int island_index) { @@ -1449,17 +1449,13 @@ static void VertsToTransData(TransInfo *t, td->ext = NULL; td->val = NULL; td->extra = eve; - if (ELEM(t->mode, TFM_BWEIGHT, TFM_VERT_CREASE)) { - td->val = bweight; - td->ival = *bweight; - } - else if (t->mode == TFM_SHRINKFATTEN) { + if (t->mode == TFM_SHRINKFATTEN) { td->ext = tx; tx->isize[0] = BM_vert_calc_shell_factor_ex(eve, no, BM_ELEM_SELECT); } } -void createTransEditVerts(TransInfo *t) +static void createTransEditVerts(bContext *UNUSED(C), TransInfo *t) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransDataExtension *tx = NULL; @@ -1589,17 +1585,6 @@ void createTransEditVerts(TransInfo *t) "TransObData ext"); } - int cd_vert_bweight_offset = -1; - int cd_vert_crease_offset = -1; - if (t->mode == TFM_BWEIGHT) { - BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_BWEIGHT); - cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); - } - else if (t->mode == TFM_VERT_CREASE) { - BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_CREASE); - cd_vert_crease_offset = CustomData_get_offset(&bm->vdata, CD_CREASE); - } - TransData *tob = tc->data; TransDataMirror *td_mirror = tc->data_mirror; BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { @@ -1632,15 +1617,9 @@ void createTransEditVerts(TransInfo *t) td_mirror++; } else if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - float *bweight = (cd_vert_bweight_offset != -1) ? - BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : - (cd_vert_crease_offset != -1) ? - BM_ELEM_CD_GET_VOID_P(eve, cd_vert_crease_offset) : - NULL; - /* Do not use the island center in case we are using islands * only to get axis for snap/rotate to normal... */ - VertsToTransData(t, tob, tx, em, eve, bweight, &island_data, island_index); + VertsToTransData(t, tob, tx, em, eve, &island_data, island_index); if (tx) { tx++; } @@ -1940,7 +1919,7 @@ static void tc_mesh_partial_types_calc(TransInfo *t, struct PartialTypeState *r_ } /* With projection, transform isn't affine. */ - if (activeSnap_with_project(t)) { + if (activeSnap_SnappingIndividual(t)) { if (partial_for_looptri == PARTIAL_TYPE_GROUP) { partial_for_looptri = PARTIAL_TYPE_ALL; } @@ -2051,12 +2030,12 @@ static void tc_mesh_transdata_mirror_apply(TransDataContainer *tc) } } -void recalcData_mesh(TransInfo *t) +static void recalcData_mesh(TransInfo *t) { bool is_canceling = t->state == TRANS_CANCEL; /* Apply corrections. */ if (!is_canceling) { - applyProject(t); + applySnappingIndividual(t); bool do_mirror = !(t->flag & T_NO_MIRROR); FOREACH_TRANS_DATA_CONTAINER (t, tc) { @@ -2145,9 +2124,16 @@ void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t) FOREACH_TRANS_DATA_CONTAINER (t, tc) { /* table needs to be created for each edit command, since vertices can move etc */ ED_mesh_mirror_spatial_table_end(tc->obedit); - /* TODO(campbell): xform: We need support for many mirror objects at once! */ + /* TODO(@campbellbarton): xform: We need support for many mirror objects at once! */ break; } } /** \} */ + +TransConvertTypeInfo TransConvertType_Mesh = { + /* flags */ (T_EDIT | T_POINTS), + /* createTransData */ createTransEditVerts, + /* recalcData */ recalcData_mesh, + /* special_aftertrans_update */ special_aftertrans_update__mesh, +}; diff --git a/source/blender/editors/transform/transform_convert_mesh_edge.c b/source/blender/editors/transform/transform_convert_mesh_edge.c index 2d6c6a933d6..b1627e62f8c 100644 --- a/source/blender/editors/transform/transform_convert_mesh_edge.c +++ b/source/blender/editors/transform/transform_convert_mesh_edge.c @@ -23,7 +23,7 @@ /** \name Edge (for crease) Transform Creation * \{ */ -void createTransEdge(TransInfo *t) +static void createTransEdge(bContext *UNUSED(C), TransInfo *t) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { @@ -67,7 +67,9 @@ void createTransEdge(TransInfo *t) /* create data we need */ if (t->mode == TFM_BWEIGHT) { - BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_EDGE_BWEIGHT); + if (!CustomData_has_layer(&em->bm->edata, CD_BWEIGHT)) { + BM_data_layer_add(em->bm, &em->bm->edata, CD_BWEIGHT); + } cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT); } else { /* if (t->mode == TFM_EDGE_CREASE) { */ @@ -99,8 +101,8 @@ void createTransEdge(TransInfo *t) td->ext = NULL; fl_ptr = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_float_offset); - td->val = fl_ptr; - td->ival = *fl_ptr; + td->loc = fl_ptr; + td->iloc[0] = *fl_ptr; td++; } @@ -108,7 +110,7 @@ void createTransEdge(TransInfo *t) } } -void recalcData_mesh_edge(TransInfo *t) +static void recalcData_mesh_edge(TransInfo *t) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY); @@ -116,3 +118,10 @@ void recalcData_mesh_edge(TransInfo *t) } /** \} */ + +TransConvertTypeInfo TransConvertType_MeshEdge = { + /* flags */ T_EDIT, + /* createTransData */ createTransEdge, + /* recalcData */ recalcData_mesh_edge, + /* special_aftertrans_update */ special_aftertrans_update__mesh, +}; diff --git a/source/blender/editors/transform/transform_convert_mesh_skin.c b/source/blender/editors/transform/transform_convert_mesh_skin.c index fdc2ba59035..376e559181e 100644 --- a/source/blender/editors/transform/transform_convert_mesh_skin.c +++ b/source/blender/editors/transform/transform_convert_mesh_skin.c @@ -66,7 +66,7 @@ static void tc_mesh_skin_transdata_create(TransDataBasic *td, td->extra = eve; } -void createTransMeshSkin(TransInfo *t) +static void createTransMeshSkin(bContext *UNUSED(C), TransInfo *t) { BLI_assert(t->mode == TFM_SKIN_RESIZE); FOREACH_TRANS_DATA_CONTAINER (t, tc) { @@ -271,7 +271,7 @@ static void tc_mesh_skin_apply_to_mirror(TransInfo *t) } } -void recalcData_mesh_skin(TransInfo *t) +static void recalcData_mesh_skin(TransInfo *t) { bool is_canceling = t->state == TRANS_CANCEL; /* mirror modifier clipping? */ @@ -289,3 +289,10 @@ void recalcData_mesh_skin(TransInfo *t) } /** \} */ + +TransConvertTypeInfo TransConvertType_MeshSkin = { + /* flags */ (T_EDIT | T_POINTS), + /* createTransData */ createTransMeshSkin, + /* recalcData */ recalcData_mesh_skin, + /* special_aftertrans_update */ NULL, +}; diff --git a/source/blender/editors/transform/transform_convert_mesh_uv.c b/source/blender/editors/transform/transform_convert_mesh_uv.c index 18868643b6d..0afdda34d36 100644 --- a/source/blender/editors/transform/transform_convert_mesh_uv.c +++ b/source/blender/editors/transform/transform_convert_mesh_uv.c @@ -234,11 +234,10 @@ static void uv_set_connectivity_distance(BMesh *bm, float *dists, const float as MEM_freeN(dists_prev); } -void createTransUVs(bContext *C, TransInfo *t) +static void createTransUVs(bContext *C, TransInfo *t) { SpaceImage *sima = CTX_wm_space_image(C); Scene *scene = t->scene; - ToolSettings *ts = CTX_data_tool_settings(C); const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; const bool is_prop_connected = (t->flag & T_PROP_CONNECTED) != 0; @@ -266,13 +265,12 @@ void createTransUVs(bContext *C, TransInfo *t) /* count */ if (is_island_center) { /* create element map with island information */ - const bool use_facesel = (ts->uv_flag & UV_SYNC_SELECTION) == 0; - elementmap = BM_uv_element_map_create(em->bm, scene, use_facesel, true, false, true); + elementmap = BM_uv_element_map_create(em->bm, scene, true, false, true, true); if (elementmap == NULL) { continue; } - island_center = MEM_callocN(sizeof(*island_center) * elementmap->totalIslands, __func__); + island_center = MEM_callocN(sizeof(*island_center) * elementmap->total_islands, __func__); } BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { @@ -317,9 +315,7 @@ void createTransUVs(bContext *C, TransInfo *t) } if (is_island_center) { - int i; - - for (i = 0; i < elementmap->totalIslands; i++) { + for (int i = 0; i < elementmap->total_islands; i++) { mul_v2_fl(island_center[i].co, 1.0f / island_center[i].co_num); mul_v2_v2(island_center[i].co, t->aspect); } @@ -403,8 +399,8 @@ void createTransUVs(bContext *C, TransInfo *t) static void flushTransUVs(TransInfo *t) { SpaceImage *sima = t->area->spacedata.first; - const bool use_pixel_snap = ((sima->pixel_snap_mode != SI_PIXEL_SNAP_DISABLED) && - (t->state != TRANS_CANCEL)); + const bool use_pixel_round = ((sima->pixel_round_mode != SI_PIXEL_ROUND_DISABLED) && + (t->state != TRANS_CANCEL)); FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData2D *td; @@ -414,7 +410,7 @@ static void flushTransUVs(TransInfo *t) aspect_inv[0] = 1.0f / t->aspect[0]; aspect_inv[1] = 1.0f / t->aspect[1]; - if (use_pixel_snap) { + if (use_pixel_round) { int size_i[2]; ED_space_image_get_size(sima, &size_i[0], &size_i[1]); size[0] = size_i[0]; @@ -426,16 +422,16 @@ static void flushTransUVs(TransInfo *t) td->loc2d[0] = td->loc[0] * aspect_inv[0]; td->loc2d[1] = td->loc[1] * aspect_inv[1]; - if (use_pixel_snap) { + if (use_pixel_round) { td->loc2d[0] *= size[0]; td->loc2d[1] *= size[1]; - switch (sima->pixel_snap_mode) { - case SI_PIXEL_SNAP_CENTER: + switch (sima->pixel_round_mode) { + case SI_PIXEL_ROUND_CENTER: td->loc2d[0] = roundf(td->loc2d[0] - 0.5f) + 0.5f; td->loc2d[1] = roundf(td->loc2d[1] - 0.5f) + 0.5f; break; - case SI_PIXEL_SNAP_CORNER: + case SI_PIXEL_ROUND_CORNER: td->loc2d[0] = roundf(td->loc2d[0]); td->loc2d[1] = roundf(td->loc2d[1]); break; @@ -448,7 +444,7 @@ static void flushTransUVs(TransInfo *t) } } -void recalcData_uv(TransInfo *t) +static void recalcData_uv(TransInfo *t) { SpaceImage *sima = t->area->spacedata.first; @@ -465,3 +461,10 @@ void recalcData_uv(TransInfo *t) } /** \} */ + +TransConvertTypeInfo TransConvertType_MeshUV = { + /* flags */ (T_EDIT | T_POINTS | T_2D_EDIT), + /* createTransData */ createTransUVs, + /* recalcData */ recalcData_uv, + /* special_aftertrans_update */ NULL, +}; diff --git a/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c b/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c new file mode 100644 index 00000000000..39705f87a0d --- /dev/null +++ b/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c @@ -0,0 +1,298 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2001-2002 NaN Holding BV. All rights reserved. */ + +/** \file + * \ingroup edtransform + */ + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_crazyspace.h" +#include "BKE_editmesh.h" +#include "BKE_modifier.h" +#include "BKE_scene.h" + +#include "ED_mesh.h" + +#include "DEG_depsgraph_query.h" + +#include "transform.h" +#include "transform_orientations.h" + +#include "transform_convert.h" + +/* -------------------------------------------------------------------- */ +/** \name Edit Mesh #CD_BWEIGHT and #CD_CREASE Transform Creation + * \{ */ + +static float *tc_mesh_cdata_transdata_center(const struct TransIslandData *island_data, + const int island_index, + BMVert *eve) +{ + if (island_data->center && island_index != -1) { + return island_data->center[island_index]; + } + return eve->co; +} + +static void tc_mesh_cdata_transdata_create(TransDataBasic *td, + BMVert *eve, + float *weight, + const struct TransIslandData *island_data, + const int island_index) +{ + BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0); + + td->loc = weight; + td->iloc[0] = *weight; + + if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + td->flag |= TD_SELECTED; + } + + copy_v3_v3(td->center, tc_mesh_cdata_transdata_center(island_data, island_index, eve)); + td->extra = eve; +} + +static void createTransMeshVertCData(bContext *UNUSED(C), TransInfo *t) +{ + BLI_assert(ELEM(t->mode, TFM_BWEIGHT, TFM_VERT_CREASE)); + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + Mesh *me = tc->obedit->data; + BMesh *bm = em->bm; + BMVert *eve; + BMIter iter; + float mtx[3][3], smtx[3][3]; + int a; + const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0; + + struct TransIslandData island_data = {NULL}; + struct TransMirrorData mirror_data = {NULL}; + struct TransMeshDataCrazySpace crazyspace_data = {NULL}; + + /* Support other objects using PET to adjust these, unless connected is enabled. */ + if ((!prop_mode || (prop_mode & T_PROP_CONNECTED)) && (bm->totvertsel == 0)) { + continue; + } + + int cd_offset = -1; + if (t->mode == TFM_BWEIGHT) { + if (!CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { + BM_data_layer_add(bm, &bm->vdata, CD_BWEIGHT); + } + cd_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); + } + else { + BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_VERT_CREASE); + cd_offset = CustomData_get_offset(&bm->vdata, CD_CREASE); + } + + if (cd_offset == -1) { + continue; + } + + int data_len = 0; + if (prop_mode) { + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + data_len++; + } + } + } + else { + data_len = bm->totvertsel; + } + + if (data_len == 0) { + continue; + } + + const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS); + if (is_island_center) { + /* In this specific case, near-by vertices will need to know + * the island of the nearest connected vertex. */ + const bool calc_single_islands = ((prop_mode & T_PROP_CONNECTED) && + (t->around == V3D_AROUND_LOCAL_ORIGINS) && + (em->selectmode & SCE_SELECT_VERTEX)); + + const bool calc_island_center = false; + const bool calc_island_axismtx = false; + + transform_convert_mesh_islands_calc( + em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data); + } + + copy_m3_m4(mtx, tc->obedit->obmat); + /* we use a pseudo-inverse so that when one of the axes is scaled to 0, + * matrix inversion still works and we can still moving along the other */ + pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); + + /* Original index of our connected vertex when connected distances are calculated. + * Optional, allocate if needed. */ + int *dists_index = NULL; + float *dists = NULL; + if (prop_mode & T_PROP_CONNECTED) { + dists = MEM_mallocN(bm->totvert * sizeof(float), __func__); + if (is_island_center) { + dists_index = MEM_mallocN(bm->totvert * sizeof(int), __func__); + } + transform_convert_mesh_connectivity_distance(em->bm, mtx, dists, dists_index); + } + + /* Create TransDataMirror. */ + if (tc->use_mirror_axis_any) { + bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; + bool use_select = (t->flag & T_PROP_EDIT) == 0; + const bool mirror_axis[3] = { + tc->use_mirror_axis_x, tc->use_mirror_axis_y, tc->use_mirror_axis_z}; + transform_convert_mesh_mirrordata_calc( + em, use_select, use_topology, mirror_axis, &mirror_data); + + if (mirror_data.vert_map) { + tc->data_mirror_len = mirror_data.mirror_elem_len; + tc->data_mirror = MEM_mallocN(mirror_data.mirror_elem_len * sizeof(*tc->data_mirror), + __func__); + + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { + if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + if (mirror_data.vert_map[a].index != -1) { + data_len--; + } + } + } + } + } + + /* Detect CrazySpace [tm]. */ + transform_convert_mesh_crazyspace_detect(t, tc, em, &crazyspace_data); + + /* Create TransData. */ + BLI_assert(data_len >= 1); + tc->data_len = data_len; + tc->data = MEM_callocN(data_len * sizeof(TransData), "TransObData(Mesh EditMode)"); + + TransData *td = tc->data; + TransDataMirror *td_mirror = tc->data_mirror; + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { + if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + continue; + } + + int island_index = -1; + if (island_data.island_vert_map) { + const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a; + island_index = island_data.island_vert_map[connected_index]; + } + + float *weight = BM_ELEM_CD_GET_VOID_P(eve, cd_offset); + if (mirror_data.vert_map && mirror_data.vert_map[a].index != -1) { + tc_mesh_cdata_transdata_create( + (TransDataBasic *)td_mirror, eve, weight, &island_data, island_index); + + int elem_index = mirror_data.vert_map[a].index; + BMVert *v_src = BM_vert_at_index(bm, elem_index); + + td_mirror->flag |= mirror_data.vert_map[a].flag; + td_mirror->loc_src = BM_ELEM_CD_GET_VOID_P(v_src, cd_offset); + td_mirror++; + } + else if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + tc_mesh_cdata_transdata_create( + (TransDataBasic *)td, eve, weight, &island_data, island_index); + + if (t->around == V3D_AROUND_LOCAL_ORIGINS) { + createSpaceNormal(td->axismtx, eve->no); + } + else { + /* Setting normals */ + copy_v3_v3(td->axismtx[2], eve->no); + td->axismtx[0][0] = td->axismtx[0][1] = td->axismtx[0][2] = td->axismtx[1][0] = + td->axismtx[1][1] = td->axismtx[1][2] = 0.0f; + } + + if (prop_mode) { + if (prop_mode & T_PROP_CONNECTED) { + td->dist = dists[a]; + } + else { + td->flag |= TD_NOTCONNECTED; + td->dist = FLT_MAX; + } + } + + /* CrazySpace */ + transform_convert_mesh_crazyspace_transdata_set( + mtx, + smtx, + crazyspace_data.defmats ? crazyspace_data.defmats[a] : NULL, + crazyspace_data.quats && BM_elem_flag_test(eve, BM_ELEM_TAG) ? + crazyspace_data.quats[a] : + NULL, + td); + + td++; + } + } + + transform_convert_mesh_islanddata_free(&island_data); + transform_convert_mesh_mirrordata_free(&mirror_data); + transform_convert_mesh_crazyspace_free(&crazyspace_data); + if (dists) { + MEM_freeN(dists); + } + if (dists_index) { + MEM_freeN(dists_index); + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Recalc Mesh Data + * \{ */ + +static void tc_mesh_cdata_apply_to_mirror(TransInfo *t) +{ + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + if (tc->use_mirror_axis_any) { + TransDataMirror *td_mirror = tc->data_mirror; + for (int i = 0; i < tc->data_mirror_len; i++, td_mirror++) { + td_mirror->loc[0] = td_mirror->loc_src[0]; + } + } + } +} + +static void recalcData_mesh_cdata(TransInfo *t) +{ + bool is_canceling = t->state == TRANS_CANCEL; + /* mirror modifier clipping? */ + if (!is_canceling) { + if (!(t->flag & T_NO_MIRROR)) { + tc_mesh_cdata_apply_to_mirror(t); + } + } + + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY); + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BKE_editmesh_looptri_and_normals_calc(em); + } +} + +/** \} */ + +TransConvertTypeInfo TransConvertType_MeshVertCData = { + /* flags */ (T_EDIT | T_POINTS), + /* createTransData */ createTransMeshVertCData, + /* recalcData */ recalcData_mesh_cdata, + /* special_aftertrans_update */ NULL, +}; diff --git a/source/blender/editors/transform/transform_convert_nla.c b/source/blender/editors/transform/transform_convert_nla.c index 2fa8fcf65ba..cfa933d1600 100644 --- a/source/blender/editors/transform/transform_convert_nla.c +++ b/source/blender/editors/transform/transform_convert_nla.c @@ -59,7 +59,7 @@ typedef struct TransDataNla { /** \name NLA Transform Creation * \{ */ -void createTransNlaData(bContext *C, TransInfo *t) +static void createTransNlaData(bContext *C, TransInfo *t) { Scene *scene = t->scene; SpaceNla *snla = NULL; @@ -82,12 +82,13 @@ void createTransNlaData(bContext *C, TransInfo *t) snla = (SpaceNla *)ac.sl; /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | + ANIMFILTER_FCURVESONLY); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); /* which side of the current frame should be allowed */ if (t->mode == TFM_TIME_EXTEND) { - t->frame_side = transform_convert_frame_side_dir_get(t, (float)CFRA); + t->frame_side = transform_convert_frame_side_dir_get(t, (float)scene->r.cfra); } else { /* normal transform - both sides of current frame are considered */ @@ -108,10 +109,10 @@ void createTransNlaData(bContext *C, TransInfo *t) /* transition strips can't get directly transformed */ if (strip->type != NLASTRIP_TYPE_TRANSITION) { if (strip->flag & NLASTRIP_FLAG_SELECT) { - if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA)) { + if (FrameOnMouseSide(t->frame_side, strip->start, (float)scene->r.cfra)) { count++; } - if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA)) { + if (FrameOnMouseSide(t->frame_side, strip->end, (float)scene->r.cfra)) { count++; } } @@ -122,7 +123,7 @@ void createTransNlaData(bContext *C, TransInfo *t) /* stop if trying to build list if nothing selected */ if (count == 0) { /* clear temp metas that may have been created but aren't needed now - * because they fell on the wrong side of CFRA + * because they fell on the wrong side of scene->r.cfra */ for (ale = anim_data.first; ale; ale = ale->next) { NlaTrack *nlt = (NlaTrack *)ale->data; @@ -181,12 +182,12 @@ void createTransNlaData(bContext *C, TransInfo *t) tdn->h2[0] = strip->end; tdn->h2[1] = yval; - center[0] = (float)CFRA; + center[0] = (float)scene->r.cfra; center[1] = yval; center[2] = 0.0f; /* set td's based on which handles are applicable */ - if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA)) { + if (FrameOnMouseSide(t->frame_side, strip->start, (float)scene->r.cfra)) { /* just set tdn to assume that it only has one handle for now */ tdn->handle = -1; @@ -206,7 +207,7 @@ void createTransNlaData(bContext *C, TransInfo *t) td->extra = tdn; td++; } - if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA)) { + if (FrameOnMouseSide(t->frame_side, strip->end, (float)scene->r.cfra)) { /* if tdn is already holding the start handle, * then we're doing both, otherwise, only end */ tdn->handle = (tdn->handle) ? 2 : 1; @@ -248,7 +249,7 @@ void createTransNlaData(bContext *C, TransInfo *t) ANIM_animdata_freelist(&anim_data); } -void recalcData_nla(TransInfo *t) +static void recalcData_nla(TransInfo *t) { SpaceNla *snla = (SpaceNla *)t->area->spacedata.first; @@ -463,7 +464,7 @@ void recalcData_nla(TransInfo *t) /** \name Special After Transform NLA * \{ */ -void special_aftertrans_update__nla(bContext *C, TransInfo *UNUSED(t)) +static void special_aftertrans_update__nla(bContext *C, TransInfo *UNUSED(t)) { bAnimContext ac; @@ -475,7 +476,7 @@ void special_aftertrans_update__nla(bContext *C, TransInfo *UNUSED(t)) if (ac.datatype) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; - short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT); + short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_FCURVESONLY); /* get channels to work on */ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); @@ -505,3 +506,10 @@ void special_aftertrans_update__nla(bContext *C, TransInfo *UNUSED(t)) } /** \} */ + +TransConvertTypeInfo TransConvertType_NLA = { + /* flags */ (T_POINTS | T_2D_EDIT), + /* createTransData */ createTransNlaData, + /* recalcData */ recalcData_nla, + /* special_aftertrans_update */ special_aftertrans_update__nla, +}; diff --git a/source/blender/editors/transform/transform_convert_node.c b/source/blender/editors/transform/transform_convert_node.c index 8281052c314..ed19789fdd8 100644 --- a/source/blender/editors/transform/transform_convert_node.c +++ b/source/blender/editors/transform/transform_convert_node.c @@ -27,6 +27,13 @@ #include "transform_convert.h" #include "transform_snap.h" +struct TransCustomDataNode { + View2DEdgePanData edgepan_data; + + /* Compare if the view has changed so we can update with `transformViewUpdate`. */ + rctf viewrect_prev; +}; + /* -------------------------------------------------------------------- */ /** \name Node Transform Creation * \{ */ @@ -89,21 +96,23 @@ static bool is_node_parent_select(bNode *node) return false; } -void createTransNodeData(TransInfo *t) +static void createTransNodeData(bContext *UNUSED(C), TransInfo *t) { const float dpi_fac = UI_DPI_FAC; SpaceNode *snode = t->area->spacedata.first; /* Custom data to enable edge panning during the node transform */ - View2DEdgePanData *customdata = MEM_callocN(sizeof(*customdata), __func__); + struct TransCustomDataNode *customdata = MEM_callocN(sizeof(*customdata), __func__); UI_view2d_edge_pan_init(t->context, - customdata, + &customdata->edgepan_data, NODE_EDGE_PAN_INSIDE_PAD, NODE_EDGE_PAN_OUTSIDE_PAD, NODE_EDGE_PAN_SPEED_RAMP, NODE_EDGE_PAN_MAX_SPEED, NODE_EDGE_PAN_DELAY, NODE_EDGE_PAN_ZOOM_INFLUENCE); + customdata->viewrect_prev = customdata->edgepan_data.initial_rect; + t->custom.type.data = customdata; t->custom.type.use_free = true; @@ -150,15 +159,15 @@ void createTransNodeData(TransInfo *t) /** \name Node Transform Creation * \{ */ -void flushTransNodes(TransInfo *t) +static void flushTransNodes(TransInfo *t) { const float dpi_fac = UI_DPI_FAC; - View2DEdgePanData *customdata = (View2DEdgePanData *)t->custom.type.data; + struct TransCustomDataNode *customdata = (struct TransCustomDataNode *)t->custom.type.data; if (t->options & CTX_VIEW2D_EDGE_PAN) { if (t->state == TRANS_CANCEL) { - UI_view2d_edge_pan_cancel(t->context, customdata); + UI_view2d_edge_pan_cancel(t->context, &customdata->edgepan_data); } else { /* Edge panning functions expect window coordinates, mval is relative to region */ @@ -166,13 +175,19 @@ void flushTransNodes(TransInfo *t) t->region->winrct.xmin + t->mval[0], t->region->winrct.ymin + t->mval[1], }; - UI_view2d_edge_pan_apply(t->context, customdata, xy); + UI_view2d_edge_pan_apply(t->context, &customdata->edgepan_data, xy); } } - /* Initial and current view2D rects for additional transform due to view panning and zooming */ - const rctf *rect_src = &customdata->initial_rect; - const rctf *rect_dst = &t->region->v2d.cur; + float offset[2] = {0.0f, 0.0f}; + if (t->state != TRANS_CANCEL) { + if (!BLI_rctf_compare(&customdata->viewrect_prev, &t->region->v2d.cur, FLT_EPSILON)) { + /* Additional offset due to change in view2D rect. */ + BLI_rctf_transform_pt_v(&t->region->v2d.cur, &customdata->viewrect_prev, offset, offset); + tranformViewUpdate(t); + customdata->viewrect_prev = t->region->v2d.cur; + } + } FOREACH_TRANS_DATA_CONTAINER (t, tc) { applyGridAbsolute(t); @@ -184,10 +199,7 @@ void flushTransNodes(TransInfo *t) bNode *node = td->extra; float loc[2]; - copy_v2_v2(loc, td2d->loc); - - /* additional offset due to change in view2D rect */ - BLI_rctf_transform_pt_v(rect_dst, rect_src, loc, loc); + add_v2_v2v2(loc, td2d->loc, offset); #ifdef USE_NODE_CENTER loc[0] -= 0.5f * BLI_rctf_size_x(&node->totr); @@ -220,7 +232,7 @@ void flushTransNodes(TransInfo *t) /** \name Special After Transform Node * \{ */ -void special_aftertrans_update__node(bContext *C, TransInfo *t) +static void special_aftertrans_update__node(bContext *C, TransInfo *t) { struct Main *bmain = CTX_data_main(C); const bool canceled = (t->state == TRANS_CANCEL); @@ -249,3 +261,10 @@ void special_aftertrans_update__node(bContext *C, TransInfo *t) } /** \} */ + +TransConvertTypeInfo TransConvertType_Node = { + /* flags */ (T_POINTS | T_2D_EDIT), + /* createTransData */ createTransNodeData, + /* recalcData */ flushTransNodes, + /* special_aftertrans_update */ special_aftertrans_update__node, +}; diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c index 5879a65eb4b..caa11fa5db4 100644 --- a/source/blender/editors/transform/transform_convert_object.c +++ b/source/blender/editors/transform/transform_convert_object.c @@ -291,9 +291,10 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) } } -static void trans_object_base_deps_flag_prepare(ViewLayer *view_layer) +static void trans_object_base_deps_flag_prepare(const Scene *scene, ViewLayer *view_layer) { - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { base->object->id.tag &= ~LIB_TAG_DOIT; } } @@ -323,11 +324,14 @@ static void flush_trans_object_base_deps_flag(Depsgraph *depsgraph, Object *obje NULL); } -static void trans_object_base_deps_flag_finish(const TransInfo *t, ViewLayer *view_layer) +static void trans_object_base_deps_flag_finish(const TransInfo *t, + const Scene *scene, + ViewLayer *view_layer) { if ((t->options & CTX_OBMODE_XFORM_OBDATA) == 0) { - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (base->object->id.tag & LIB_TAG_DOIT) { base->flag_legacy |= BA_SNAP_FIX_DEPS_FIASCO; } @@ -352,13 +356,14 @@ static void set_trans_object_base_flags(TransInfo *t) return; } /* Makes sure base flags and object flags are identical. */ - BKE_scene_base_flag_to_objects(t->view_layer); + BKE_scene_base_flag_to_objects(t->scene, t->view_layer); /* Make sure depsgraph is here. */ DEG_graph_relations_update(depsgraph); /* Clear all flags we need. It will be used to detect dependencies. */ - trans_object_base_deps_flag_prepare(view_layer); + trans_object_base_deps_flag_prepare(scene, view_layer); /* Traverse all bases and set all possible flags. */ - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { base->flag_legacy &= ~(BA_WAS_SEL | BA_TRANSFORM_LOCKED_IN_PLACE); if (BASE_SELECTED_EDITABLE(v3d, base)) { Object *ob = base->object; @@ -392,7 +397,7 @@ static void set_trans_object_base_flags(TransInfo *t) /* Store temporary bits in base indicating that base is being modified * (directly or indirectly) by transforming objects. */ - trans_object_base_deps_flag_finish(t, view_layer); + trans_object_base_deps_flag_finish(t, scene, view_layer); } static bool mark_children(Object *ob) @@ -420,11 +425,11 @@ static int count_proportional_objects(TransInfo *t) Scene *scene = t->scene; Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, view_layer); /* Clear all flags we need. It will be used to detect dependencies. */ - trans_object_base_deps_flag_prepare(view_layer); + trans_object_base_deps_flag_prepare(scene, view_layer); /* Rotations around local centers are allowed to propagate, so we take all objects. */ if (!((t->around == V3D_AROUND_LOCAL_ORIGINS) && (ELEM(t->mode, TFM_ROTATION, TFM_TRACKBALL)))) { /* Mark all parents. */ - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (BASE_SELECTED_EDITABLE(v3d, base) && BASE_SELECTABLE(v3d, base)) { Object *parent = base->object->parent; /* flag all parents */ @@ -435,7 +440,7 @@ static int count_proportional_objects(TransInfo *t) } } /* Mark all children. */ - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { /* all base not already selected or marked that is editable */ if ((base->object->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 && (base->flag & BASE_SELECTED) == 0 && @@ -445,7 +450,7 @@ static int count_proportional_objects(TransInfo *t) } } /* Flush changed flags to all dependencies. */ - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *ob = base->object; /* If base is not selected, not a parent of selection or not a child of * selection and it is editable and selectable. @@ -460,16 +465,17 @@ static int count_proportional_objects(TransInfo *t) /* Store temporary bits in base indicating that base is being modified * (directly or indirectly) by transforming objects. */ - trans_object_base_deps_flag_finish(t, view_layer); + trans_object_base_deps_flag_finish(t, scene, view_layer); return total; } static void clear_trans_object_base_flags(TransInfo *t) { + Scene *scene = t->scene; ViewLayer *view_layer = t->view_layer; - Base *base; - for (base = view_layer->object_bases.first; base; base = base->next) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (base->flag_legacy & BA_WAS_SEL) { ED_object_base_select(base, BA_SELECT); } @@ -480,7 +486,7 @@ static void clear_trans_object_base_flags(TransInfo *t) } } -void createTransObject(bContext *C, TransInfo *t) +static void createTransObject(bContext *C, TransInfo *t) { Main *bmain = CTX_data_main(C); TransData *td = NULL; @@ -559,11 +565,12 @@ void createTransObject(bContext *C, TransInfo *t) CTX_DATA_END; if (is_prop_edit) { + Scene *scene = t->scene; ViewLayer *view_layer = t->view_layer; View3D *v3d = t->view; - Base *base; - for (base = view_layer->object_bases.first; base; base = base->next) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *ob = base->object; /* if base is not selected, not a parent of selection @@ -592,10 +599,12 @@ void createTransObject(bContext *C, TransInfo *t) } } + Scene *scene = t->scene; ViewLayer *view_layer = t->view_layer; View3D *v3d = t->view; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *ob = base->object; /* if base is not selected, not a parent of selection @@ -640,9 +649,11 @@ void createTransObject(bContext *C, TransInfo *t) } } + Scene *scene = t->scene; ViewLayer *view_layer = t->view_layer; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *ob = base->object; if (ob->parent != NULL) { if (ob->parent && !BLI_gset_haskey(objects_in_transdata, ob->parent) && @@ -672,7 +683,7 @@ void createTransObject(bContext *C, TransInfo *t) } } - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *ob = base->object; if (BASE_XFORM_INDIRECT(base) || BLI_gset_haskey(objects_in_transdata, ob)) { @@ -732,8 +743,8 @@ static void autokeyframe_object( KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene); ListBase dsources = {NULL, NULL}; Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); - const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, - (float)CFRA); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( + depsgraph, (float)scene->r.cfra); eInsertKeyFlags flag = 0; /* Get flags used for inserting keyframes. */ @@ -782,7 +793,8 @@ static void autokeyframe_object( } else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) { if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) { - if (ob != OBACT(view_layer)) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (ob != BKE_view_layer_active_object_get(view_layer)) { do_loc = true; } } @@ -796,7 +808,8 @@ static void autokeyframe_object( } else if (tmode == TFM_RESIZE) { if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) { - if (ob != OBACT(view_layer)) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (ob != BKE_view_layer_active_object_get(view_layer)) { do_loc = true; } } @@ -860,12 +873,12 @@ static bool motionpath_need_update_object(Scene *scene, Object *ob) /** \name Recalc Data object * \{ */ -void recalcData_objects(TransInfo *t) +static void recalcData_objects(TransInfo *t) { bool motionpath_update = false; if (t->state != TRANS_CANCEL) { - applyProject(t); + applySnappingIndividual(t); } FOREACH_TRANS_DATA_CONTAINER (t, tc) { @@ -918,7 +931,7 @@ void recalcData_objects(TransInfo *t) /** \name Special After Transform Object * \{ */ -void special_aftertrans_update__object(bContext *C, TransInfo *t) +static void special_aftertrans_update__object(bContext *C, TransInfo *t) { BLI_assert(t->options & CTX_OBJECT); @@ -991,3 +1004,10 @@ void special_aftertrans_update__object(bContext *C, TransInfo *t) } /** \} */ + +TransConvertTypeInfo TransConvertType_Object = { + /* flags */ 0, + /* createTransData */ createTransObject, + /* recalcData */ recalcData_objects, + /* special_aftertrans_update */ special_aftertrans_update__object, +}; diff --git a/source/blender/editors/transform/transform_convert_object_texspace.c b/source/blender/editors/transform/transform_convert_object_texspace.c index 1f58ec80f02..839bf6b77b3 100644 --- a/source/blender/editors/transform/transform_convert_object_texspace.c +++ b/source/blender/editors/transform/transform_convert_object_texspace.c @@ -11,6 +11,7 @@ #include "BKE_animsys.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_object.h" #include "BKE_report.h" @@ -29,7 +30,7 @@ * * \{ */ -void createTransTexspace(TransInfo *t) +static void createTransTexspace(bContext *UNUSED(C), TransInfo *t) { ViewLayer *view_layer = t->view_layer; TransData *td; @@ -37,7 +38,8 @@ void createTransTexspace(TransInfo *t) ID *id; char *texflag; - ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + ob = BKE_view_layer_active_object_get(view_layer); if (ob == NULL) { /* Shouldn't logically happen, but still. */ return; @@ -86,11 +88,11 @@ void createTransTexspace(TransInfo *t) /** \name Recalc Data object * \{ */ -void recalcData_texspace(TransInfo *t) +static void recalcData_texspace(TransInfo *t) { if (t->state != TRANS_CANCEL) { - applyProject(t); + applySnappingIndividual(t); } FOREACH_TRANS_DATA_CONTAINER (t, tc) { @@ -106,3 +108,10 @@ void recalcData_texspace(TransInfo *t) } /** \} */ + +TransConvertTypeInfo TransConvertType_ObjectTexSpace = { + /* flags */ 0, + /* createTransData */ createTransTexspace, + /* recalcData */ recalcData_texspace, + /* special_aftertrans_update */ NULL, +}; diff --git a/source/blender/editors/transform/transform_convert_paintcurve.c b/source/blender/editors/transform/transform_convert_paintcurve.c index b2566016496..61b1cb9493b 100644 --- a/source/blender/editors/transform/transform_convert_paintcurve.c +++ b/source/blender/editors/transform/transform_convert_paintcurve.c @@ -108,7 +108,7 @@ static void PaintCurvePointToTransData(PaintCurvePoint *pcp, } } -void createTransPaintCurveVerts(bContext *C, TransInfo *t) +static void createTransPaintCurveVerts(bContext *C, TransInfo *t) { Paint *paint = BKE_paint_get_active_from_context(C); PaintCurve *pc; @@ -188,7 +188,7 @@ void createTransPaintCurveVerts(bContext *C, TransInfo *t) /** \name Paint Curve Transform Flush * \{ */ -void flushTransPaintCurve(TransInfo *t) +static void flushTransPaintCurve(TransInfo *t) { int i; @@ -204,3 +204,10 @@ void flushTransPaintCurve(TransInfo *t) } /** \} */ + +TransConvertTypeInfo TransConvertType_PaintCurve = { + /* flags */ (T_POINTS | T_2D_EDIT), + /* createTransData */ createTransPaintCurveVerts, + /* recalcData */ flushTransPaintCurve, + /* special_aftertrans_update */ NULL, +}; diff --git a/source/blender/editors/transform/transform_convert_particle.c b/source/blender/editors/transform/transform_convert_particle.c index d7b0f378c8a..3e056b6a048 100644 --- a/source/blender/editors/transform/transform_convert_particle.c +++ b/source/blender/editors/transform/transform_convert_particle.c @@ -13,6 +13,7 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_particle.h" #include "BKE_pointcache.h" @@ -28,13 +29,14 @@ /** \name Particle Edit Transform Creation * \{ */ -void createTransParticleVerts(TransInfo *t) +static void createTransParticleVerts(bContext *UNUSED(C), TransInfo *t) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = NULL; TransDataExtension *tx; - Object *ob = OBACT(t->view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *ob = BKE_view_layer_active_object_get(t->view_layer); ParticleEditSettings *pset = PE_settings(t->scene); PTCacheEdit *edit = PE_get_current(t->depsgraph, t->scene, ob); ParticleSystem *psys = NULL; @@ -183,7 +185,8 @@ static void flushTransParticles(TransInfo *t) FOREACH_TRANS_DATA_CONTAINER (t, tc) { Scene *scene = t->scene; ViewLayer *view_layer = t->view_layer; - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); PTCacheEdit *edit = PE_get_current(t->depsgraph, scene, ob); ParticleSystem *psys = edit->psys; PTCacheEditPoint *point; @@ -223,7 +226,7 @@ static void flushTransParticles(TransInfo *t) } } - PE_update_object(t->depsgraph, scene, OBACT(view_layer), 1); + PE_update_object(t->depsgraph, scene, ob, 1); BKE_particle_batch_cache_dirty_tag(psys, BKE_PARTICLE_BATCH_DIRTY_ALL); DEG_id_tag_update(&ob->id, ID_RECALC_PSYS_REDO); } @@ -235,12 +238,19 @@ static void flushTransParticles(TransInfo *t) /** \name Recalc Transform Particles Data * \{ */ -void recalcData_particles(TransInfo *t) +static void recalcData_particles(TransInfo *t) { if (t->state != TRANS_CANCEL) { - applyProject(t); + applySnappingIndividual(t); } flushTransParticles(t); } /** \} */ + +TransConvertTypeInfo TransConvertType_Particle = { + /* flags */ T_POINTS, + /* createTransData */ createTransParticleVerts, + /* recalcData */ recalcData_particles, + /* special_aftertrans_update */ NULL, +}; diff --git a/source/blender/editors/transform/transform_convert_sculpt.c b/source/blender/editors/transform/transform_convert_sculpt.c index 5bf6bfa8644..3792cfefe06 100644 --- a/source/blender/editors/transform/transform_convert_sculpt.c +++ b/source/blender/editors/transform/transform_convert_sculpt.c @@ -10,6 +10,7 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_paint.h" #include "BKE_report.h" @@ -23,7 +24,7 @@ /** \name Sculpt Transform Creation * \{ */ -void createTransSculpt(bContext *C, TransInfo *t) +static void createTransSculpt(bContext *C, TransInfo *t) { TransData *td; @@ -33,7 +34,8 @@ void createTransSculpt(bContext *C, TransInfo *t) return; } - Object *ob = OBACT(t->view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *ob = BKE_view_layer_active_object_get(t->view_layer); SculptSession *ss = ob->sculpt; { @@ -85,7 +87,7 @@ void createTransSculpt(bContext *C, TransInfo *t) copy_m3_m4(td->axismtx, ob->obmat); BLI_assert(!(t->options & CTX_PAINT_CURVE)); - ED_sculpt_init_transform(C, ob); + ED_sculpt_init_transform(C, ob, t->undo_name); } /** \} */ @@ -94,13 +96,14 @@ void createTransSculpt(bContext *C, TransInfo *t) /** \name Recalc Data object * \{ */ -void recalcData_sculpt(TransInfo *t) +static void recalcData_sculpt(TransInfo *t) { - Object *ob = OBACT(t->view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *ob = BKE_view_layer_active_object_get(t->view_layer); ED_sculpt_update_modal_transform(t->context, ob); } -void special_aftertrans_update__sculpt(bContext *C, TransInfo *t) +static void special_aftertrans_update__sculpt(bContext *C, TransInfo *t) { Scene *scene = t->scene; if (!BKE_id_is_editable(CTX_data_main(C), &scene->id)) { @@ -108,9 +111,17 @@ void special_aftertrans_update__sculpt(bContext *C, TransInfo *t) return; } - Object *ob = OBACT(t->view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *ob = BKE_view_layer_active_object_get(t->view_layer); BLI_assert(!(t->options & CTX_PAINT_CURVE)); ED_sculpt_end_transform(C, ob); } /** \} */ + +TransConvertTypeInfo TransConvertType_Sculpt = { + /* flags */ 0, + /* createTransData */ createTransSculpt, + /* recalcData */ recalcData_sculpt, + /* special_aftertrans_update */ special_aftertrans_update__sculpt, +}; diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c index 226b0f84f14..ddc99caeef5 100644 --- a/source/blender/editors/transform/transform_convert_sequencer.c +++ b/source/blender/editors/transform/transform_convert_sequencer.c @@ -90,9 +90,9 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *r_count, int *r_flag) if (t->mode == TFM_TIME_EXTEND) { /* *** Extend Transform *** */ - int cfra = CFRA; - int left = SEQ_time_left_handle_frame_get(seq); - int right = SEQ_time_right_handle_frame_get(seq); + int cfra = scene->r.cfra; + int left = SEQ_time_left_handle_frame_get(scene, seq); + int right = SEQ_time_right_handle_frame_get(scene, seq); if (((seq->flag & SELECT) == 0 || SEQ_transform_is_locked(channels, seq))) { *r_count = 0; @@ -163,8 +163,13 @@ static int SeqTransCount(TransInfo *t, ListBase *seqbase) return tot; } -static TransData *SeqToTransData( - TransData *td, TransData2D *td2d, TransDataSeq *tdsq, Sequence *seq, int flag, int sel_flag) +static TransData *SeqToTransData(Scene *scene, + TransData *td, + TransData2D *td2d, + TransDataSeq *tdsq, + Sequence *seq, + int flag, + int sel_flag) { int start_left; @@ -173,16 +178,16 @@ static TransData *SeqToTransData( /* Use seq_tx_get_final_left() and an offset here * so transform has the left hand location of the strip. * tdsq->start_offset is used when flushing the tx data back */ - start_left = SEQ_time_left_handle_frame_get(seq); + start_left = SEQ_time_left_handle_frame_get(scene, seq); td2d->loc[0] = start_left; tdsq->start_offset = start_left - seq->start; /* use to apply the original location */ break; case SEQ_LEFTSEL: - start_left = SEQ_time_left_handle_frame_get(seq); + start_left = SEQ_time_left_handle_frame_get(scene, seq); td2d->loc[0] = start_left; break; case SEQ_RIGHTSEL: - td2d->loc[0] = SEQ_time_right_handle_frame_get(seq); + td2d->loc[0] = SEQ_time_right_handle_frame_get(scene, seq); break; } @@ -227,6 +232,7 @@ static int SeqToTransData_build( TransInfo *t, ListBase *seqbase, TransData *td, TransData2D *td2d, TransDataSeq *tdsq) { Sequence *seq; + Scene *scene = t->scene; int count, flag; int tot = 0; @@ -238,16 +244,16 @@ static int SeqToTransData_build( if (flag & SELECT) { if (flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) { if (flag & SEQ_LEFTSEL) { - SeqToTransData(td++, td2d++, tdsq++, seq, flag, SEQ_LEFTSEL); + SeqToTransData(scene, td++, td2d++, tdsq++, seq, flag, SEQ_LEFTSEL); tot++; } if (flag & SEQ_RIGHTSEL) { - SeqToTransData(td++, td2d++, tdsq++, seq, flag, SEQ_RIGHTSEL); + SeqToTransData(scene, td++, td2d++, tdsq++, seq, flag, SEQ_RIGHTSEL); tot++; } } else { - SeqToTransData(td++, td2d++, tdsq++, seq, flag, SELECT); + SeqToTransData(scene, td++, td2d++, tdsq++, seq, flag, SELECT); tot++; } } @@ -275,7 +281,7 @@ static void seq_transform_cancel(TransInfo *t, SeqCollection *transformed_strips SEQ_ITERATOR_FOREACH (seq, transformed_strips) { /* Handle pre-existing overlapping strips even when operator is canceled. * This is necessary for SEQUENCER_OT_duplicate_move macro for example. */ - if (SEQ_transform_test_overlap(seqbase, seq)) { + if (SEQ_transform_test_overlap(t->scene, seqbase, seq)) { SEQ_transform_seqbase_shuffle(seqbase, seq, t->scene); } } @@ -318,7 +324,8 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c } SeqCollection *transformed_strips = seq_transform_collection_from_transdata(tc); - SEQ_collection_expand(seqbase_active_get(t), transformed_strips, SEQ_query_strip_effect_chain); + SEQ_collection_expand( + t->scene, seqbase_active_get(t), transformed_strips, SEQ_query_strip_effect_chain); Sequence *seq; SEQ_ITERATOR_FOREACH (seq, transformed_strips) { @@ -363,11 +370,11 @@ typedef enum SeqInputSide { SEQ_INPUT_RIGHT = 1, } SeqInputSide; -static Sequence *effect_input_get(Sequence *effect, SeqInputSide side) +static Sequence *effect_input_get(const Scene *scene, Sequence *effect, SeqInputSide side) { Sequence *input = effect->seq1; - if (effect->seq2 && (SEQ_time_left_handle_frame_get(effect->seq2) - - SEQ_time_left_handle_frame_get(effect->seq1)) * + if (effect->seq2 && (SEQ_time_left_handle_frame_get(scene, effect->seq2) - + SEQ_time_left_handle_frame_get(scene, effect->seq1)) * side > 0) { input = effect->seq2; @@ -375,12 +382,12 @@ static Sequence *effect_input_get(Sequence *effect, SeqInputSide side) return input; } -static Sequence *effect_base_input_get(Sequence *effect, SeqInputSide side) +static Sequence *effect_base_input_get(const Scene *scene, Sequence *effect, SeqInputSide side) { Sequence *input = effect, *seq_iter = effect; while (seq_iter != NULL) { input = seq_iter; - seq_iter = effect_input_get(seq_iter, side); + seq_iter = effect_input_get(scene, seq_iter, side); } return input; } @@ -400,7 +407,7 @@ static SeqCollection *query_time_dependent_strips_strips(TransInfo *t) SeqCollection *strips_no_handles = query_selected_strips_no_handles(seqbase); /* Selection is needed as reference for related strips. */ SeqCollection *dependent = SEQ_collection_duplicate(strips_no_handles); - SEQ_collection_expand(seqbase, strips_no_handles, SEQ_query_strip_effect_chain); + SEQ_collection_expand(t->scene, seqbase, strips_no_handles, SEQ_query_strip_effect_chain); bool strip_added = true; while (strip_added) { @@ -430,7 +437,7 @@ static SeqCollection *query_time_dependent_strips_strips(TransInfo *t) * With single input effect, it is less likely desirable to move animation. */ SeqCollection *selected_strips = SEQ_query_selected_strips(seqbase); - SEQ_collection_expand(seqbase, selected_strips, SEQ_query_strip_effect_chain); + SEQ_collection_expand(t->scene, seqbase, selected_strips, SEQ_query_strip_effect_chain); Sequence *seq; SEQ_ITERATOR_FOREACH (seq, selected_strips) { /* Check only 2 input effects. */ @@ -439,8 +446,8 @@ static SeqCollection *query_time_dependent_strips_strips(TransInfo *t) } /* Find immediate base inputs(left and right side). */ - Sequence *input_left = effect_base_input_get(seq, SEQ_INPUT_LEFT); - Sequence *input_right = effect_base_input_get(seq, SEQ_INPUT_RIGHT); + Sequence *input_left = effect_base_input_get(t->scene, seq, SEQ_INPUT_LEFT); + Sequence *input_right = effect_base_input_get(t->scene, seq, SEQ_INPUT_RIGHT); if ((input_left->flag & SEQ_RIGHTSEL) != 0 && (input_right->flag & SEQ_LEFTSEL) != 0) { SEQ_collection_append_strip(seq, dependent); @@ -458,7 +465,7 @@ static SeqCollection *query_time_dependent_strips_strips(TransInfo *t) return dependent; } -void createTransSeqData(TransInfo *t) +static void createTransSeqData(bContext *UNUSED(C), TransInfo *t) { Scene *scene = t->scene; Editing *ed = SEQ_editing_get(t->scene); @@ -482,7 +489,7 @@ void createTransSeqData(TransInfo *t) } tc->custom.type.free_cb = freeSeqData; - t->frame_side = transform_convert_frame_side_dir_get(t, (float)CFRA); + t->frame_side = transform_convert_frame_side_dir_get(t, (float)scene->r.cfra); count = SeqTransCount(t, ed->seqbasep); @@ -571,6 +578,8 @@ static void flushTransSeq(TransInfo *t) TransDataSeq *tdsq = NULL; Sequence *seq; + Scene *scene = t->scene; + TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); /* This is calculated for offsetting animation of effects that change position with inputs. @@ -594,7 +603,7 @@ static void flushTransSeq(TransInfo *t) case SELECT: { if (SEQ_transform_sequence_can_be_translated(seq)) { offset = new_frame - tdsq->start_offset - seq->start; - SEQ_transform_translate_sequence(t->scene, seq, offset); + SEQ_transform_translate_sequence(scene, seq, offset); if (abs(offset) > abs(max_offset)) { max_offset = offset; } @@ -604,24 +613,22 @@ static void flushTransSeq(TransInfo *t) break; } case SEQ_LEFTSEL: { /* No vertical transform. */ - int old_startdisp = SEQ_time_left_handle_frame_get(seq); + int old_startdisp = SEQ_time_left_handle_frame_get(scene, seq); SEQ_time_left_handle_frame_set(t->scene, seq, new_frame); - SEQ_transform_handle_xlimits( - t->scene, seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL); SEQ_transform_fix_single_image_seq_offsets(t->scene, seq); - if (abs(SEQ_time_left_handle_frame_get(seq) - old_startdisp) > abs(max_offset)) { - max_offset = SEQ_time_left_handle_frame_get(seq) - old_startdisp; + + if (abs(SEQ_time_left_handle_frame_get(scene, seq) - old_startdisp) > abs(max_offset)) { + max_offset = SEQ_time_left_handle_frame_get(scene, seq) - old_startdisp; } break; } case SEQ_RIGHTSEL: { /* No vertical transform. */ - int old_enddisp = SEQ_time_right_handle_frame_get(seq); + int old_enddisp = SEQ_time_right_handle_frame_get(scene, seq); SEQ_time_right_handle_frame_set(t->scene, seq, new_frame); - SEQ_transform_handle_xlimits( - t->scene, seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL); SEQ_transform_fix_single_image_seq_offsets(t->scene, seq); - if (abs(SEQ_time_right_handle_frame_get(seq) - old_enddisp) > abs(max_offset)) { - max_offset = SEQ_time_right_handle_frame_get(seq) - old_enddisp; + + if (abs(SEQ_time_right_handle_frame_get(scene, seq) - old_enddisp) > abs(max_offset)) { + max_offset = SEQ_time_right_handle_frame_get(scene, seq) - old_enddisp; } break; } @@ -638,12 +645,13 @@ static void flushTransSeq(TransInfo *t) /* need to do the overlap check in a new loop otherwise adjacent strips * will not be updated and we'll get false positives */ SeqCollection *transformed_strips = seq_transform_collection_from_transdata(tc); - SEQ_collection_expand(seqbase_active_get(t), transformed_strips, SEQ_query_strip_effect_chain); + SEQ_collection_expand( + t->scene, seqbase_active_get(t), transformed_strips, SEQ_query_strip_effect_chain); SEQ_ITERATOR_FOREACH (seq, transformed_strips) { /* test overlap, displays red outline */ seq->flag &= ~SEQ_OVERLAP; - if (SEQ_transform_test_overlap(seqbasep, seq)) { + if (SEQ_transform_test_overlap(scene, seqbasep, seq)) { seq->flag |= SEQ_OVERLAP; } } @@ -651,7 +659,7 @@ static void flushTransSeq(TransInfo *t) SEQ_collection_free(transformed_strips); } -void recalcData_sequencer(TransInfo *t) +static void recalcData_sequencer(TransInfo *t) { TransData *td; int a; @@ -681,7 +689,7 @@ void recalcData_sequencer(TransInfo *t) /** \name Special After Transform Sequencer * \{ */ -void special_aftertrans_update__sequencer(bContext *UNUSED(C), TransInfo *t) +static void special_aftertrans_update__sequencer(bContext *UNUSED(C), TransInfo *t) { if (t->state == TRANS_CANCEL) { return; @@ -700,12 +708,12 @@ void special_aftertrans_update__sequencer(bContext *UNUSED(C), TransInfo *t) if (t->mode == TFM_SEQ_SLIDE) { if (t->frame_side == 'B') { ED_markers_post_apply_transform( - &t->scene->markers, t->scene, TFM_TIME_TRANSLATE, t->values[0], t->frame_side); + &t->scene->markers, t->scene, TFM_TIME_TRANSLATE, t->values_final[0], t->frame_side); } } else if (ELEM(t->frame_side, 'L', 'R')) { ED_markers_post_apply_transform( - &t->scene->markers, t->scene, TFM_TIME_EXTEND, t->values[0], t->frame_side); + &t->scene->markers, t->scene, TFM_TIME_EXTEND, t->values_final[0], t->frame_side); } } } @@ -726,3 +734,10 @@ void transform_convert_sequencer_channel_clamp(TransInfo *t, float r_val[2]) } /** \} */ + +TransConvertTypeInfo TransConvertType_Sequencer = { + /* flags */ (T_POINTS | T_2D_EDIT), + /* createTransData */ createTransSeqData, + /* recalcData */ recalcData_sequencer, + /* special_aftertrans_update */ special_aftertrans_update__sequencer, +}; diff --git a/source/blender/editors/transform/transform_convert_sequencer_image.c b/source/blender/editors/transform/transform_convert_sequencer_image.c index 76c6632039a..3d0c3ddaa4c 100644 --- a/source/blender/editors/transform/transform_convert_sequencer_image.c +++ b/source/blender/editors/transform/transform_convert_sequencer_image.c @@ -105,7 +105,7 @@ static void freeSeqData(TransInfo *UNUSED(t), MEM_freeN(td->extra); } -void createTransSeqImageData(TransInfo *t) +static void createTransSeqImageData(bContext *UNUSED(C), TransInfo *t) { Editing *ed = SEQ_editing_get(t->scene); const SpaceSeq *sseq = t->area->spacedata.first; @@ -123,7 +123,8 @@ void createTransSeqImageData(TransInfo *t) ListBase *seqbase = SEQ_active_seqbase_get(ed); ListBase *channels = SEQ_channels_displayed_get(ed); - SeqCollection *strips = SEQ_query_rendered_strips(channels, seqbase, t->scene->r.cfra, 0); + SeqCollection *strips = SEQ_query_rendered_strips( + t->scene, channels, seqbase, t->scene->r.cfra, 0); SEQ_filter_selected_strips(strips); const int count = SEQ_collection_len(strips); @@ -172,25 +173,25 @@ static bool autokeyframe_sequencer_image(bContext *C, bool changed = false; if (do_rot) { prop = RNA_struct_find_property(&ptr, "rotation"); - changed |= ED_autokeyframe_property(C, scene, &ptr, prop, -1, CFRA, false); + changed |= ED_autokeyframe_property(C, scene, &ptr, prop, -1, scene->r.cfra, false); } if (do_loc) { prop = RNA_struct_find_property(&ptr, "offset_x"); - changed |= ED_autokeyframe_property(C, scene, &ptr, prop, -1, CFRA, false); + changed |= ED_autokeyframe_property(C, scene, &ptr, prop, -1, scene->r.cfra, false); prop = RNA_struct_find_property(&ptr, "offset_y"); - changed |= ED_autokeyframe_property(C, scene, &ptr, prop, -1, CFRA, false); + changed |= ED_autokeyframe_property(C, scene, &ptr, prop, -1, scene->r.cfra, false); } if (do_scale) { prop = RNA_struct_find_property(&ptr, "scale_x"); - changed |= ED_autokeyframe_property(C, scene, &ptr, prop, -1, CFRA, false); + changed |= ED_autokeyframe_property(C, scene, &ptr, prop, -1, scene->r.cfra, false); prop = RNA_struct_find_property(&ptr, "scale_y"); - changed |= ED_autokeyframe_property(C, scene, &ptr, prop, -1, CFRA, false); + changed |= ED_autokeyframe_property(C, scene, &ptr, prop, -1, scene->r.cfra, false); } return changed; } -void recalcData_sequencer_image(TransInfo *t) +static void recalcData_sequencer_image(TransInfo *t) { TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); TransData *td = NULL; @@ -246,7 +247,7 @@ void recalcData_sequencer_image(TransInfo *t) } } -void special_aftertrans_update__sequencer_image(bContext *UNUSED(C), TransInfo *t) +static void special_aftertrans_update__sequencer_image(bContext *UNUSED(C), TransInfo *t) { TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); @@ -270,3 +271,10 @@ void special_aftertrans_update__sequencer_image(bContext *UNUSED(C), TransInfo * } } } + +TransConvertTypeInfo TransConvertType_SequencerImage = { + /* flags */ (T_POINTS | T_2D_EDIT), + /* createTransData */ createTransSeqImageData, + /* recalcData */ recalcData_sequencer_image, + /* special_aftertrans_update */ special_aftertrans_update__sequencer_image, +}; diff --git a/source/blender/editors/transform/transform_convert_tracking.c b/source/blender/editors/transform/transform_convert_tracking.c index d447cd71a40..c0c660289a5 100644 --- a/source/blender/editors/transform/transform_convert_tracking.c +++ b/source/blender/editors/transform/transform_convert_tracking.c @@ -518,7 +518,7 @@ static void createTransTrackingCurvesData(bContext *C, TransInfo *t) } } -void createTransTrackingData(bContext *C, TransInfo *t) +static void createTransTrackingData(bContext *C, TransInfo *t) { ARegion *region = CTX_wm_region(C); SpaceClip *sc = CTX_wm_space_clip(C); @@ -694,7 +694,7 @@ static void flushTransTracking(TransInfo *t) } } -void recalcData_tracking(TransInfo *t) +static void recalcData_tracking(TransInfo *t) { SpaceClip *sc = t->area->spacedata.first; @@ -747,7 +747,7 @@ void recalcData_tracking(TransInfo *t) /** \name Special After Transform Tracking * \{ */ -void special_aftertrans_update__movieclip(bContext *C, TransInfo *t) +static void special_aftertrans_update__movieclip(bContext *C, TransInfo *t) { SpaceClip *sc = t->area->spacedata.first; MovieClip *clip = ED_space_clip_get_clip(sc); @@ -790,3 +790,10 @@ void special_aftertrans_update__movieclip(bContext *C, TransInfo *t) } /** \} */ + +TransConvertTypeInfo TransConvertType_Tracking = { + /* flags */ (T_POINTS | T_2D_EDIT), + /* createTransData */ createTransTrackingData, + /* recalcData */ recalcData_tracking, + /* special_aftertrans_update */ special_aftertrans_update__movieclip, +}; diff --git a/source/blender/editors/transform/transform_draw_cursors.c b/source/blender/editors/transform/transform_draw_cursors.c index 42942493dc3..b5a8decc390 100644 --- a/source/blender/editors/transform/transform_draw_cursors.c +++ b/source/blender/editors/transform/transform_draw_cursors.c @@ -116,7 +116,7 @@ void transform_draw_cursor_draw(bContext *UNUSED(C), int x, int y, void *customd /* Dashed lines first. */ if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) { GPU_line_width(DASH_WIDTH); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); immUniform1i("colors_len", 0); /* "simple" mode */ immUniformThemeColor3(TH_VIEW_OVERLAY); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index e45cac36736..03c53e1b3d2 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -176,7 +176,8 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve { Scene *sce = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obact = OBACT(view_layer); + BKE_view_layer_synced_ensure(sce, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT; ToolSettings *ts = CTX_data_tool_settings(C); ARegion *region = CTX_wm_region(C); @@ -333,7 +334,8 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } else if (t->spacetype == SPACE_IMAGE) { SpaceImage *sima = area->spacedata.first; - if (ED_space_image_show_uvedit(sima, OBACT(t->view_layer))) { + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + if (ED_space_image_show_uvedit(sima, BKE_view_layer_active_object_get(t->view_layer))) { /* UV transform */ } else if (sima->mode == SI_MODE_MASK) { @@ -555,7 +557,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } else { /* Release confirms preference should not affect node editor (T69288, T70504). */ - if (ISMOUSE(t->launch_event) && + if (ISMOUSE_BUTTON(t->launch_event) && ((U.flag & USER_RELEASECONFIRM) || (t->spacetype == SPACE_NODE))) { /* Global "release confirm" on mouse bindings */ t->flag |= T_RELEASE_CONFIRM; @@ -1066,8 +1068,8 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) } } else if (t->options & CTX_POSE_BONE) { - ViewLayer *view_layer = t->view_layer; - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *ob = BKE_view_layer_active_object_get(t->view_layer); if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) { mul_m4_v3(ob->obmat, r_center); return true; @@ -1083,11 +1085,10 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) } else { /* object mode */ - ViewLayer *view_layer = t->view_layer; - Object *ob = OBACT(view_layer); - Base *base = BASACT(view_layer); - if (ob && ((!select_only) || ((base->flag & BASE_SELECTED) != 0))) { - copy_v3_v3(r_center, ob->obmat[3]); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Base *base = BKE_view_layer_active_base_get(t->view_layer); + if (base && ((!select_only) || ((base->flag & BASE_SELECTED) != 0))) { + copy_v3_v3(r_center, base->object->obmat[3]); return true; } } @@ -1132,6 +1133,33 @@ static void calculateCenter_FromAround(TransInfo *t, int around, float r_center[ } } +static void calculateZfac(TransInfo *t) +{ + /* ED_view3d_calc_zfac() defines a factor for perspective depth correction, + * used in ED_view3d_win_to_delta() */ + + /* zfac is only used convertViewVec only in cases operator was invoked in RGN_TYPE_WINDOW + * and never used in other cases. + * + * We need special case here as well, since ED_view3d_calc_zfac will crash when called + * for a region different from RGN_TYPE_WINDOW. + */ + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { + t->zfac = ED_view3d_calc_zfac(t->region->regiondata, t->center_global); + } + else if (t->spacetype == SPACE_IMAGE) { + SpaceImage *sima = t->area->spacedata.first; + t->zfac = 1.0f / sima->zoom; + } + else if (t->region) { + View2D *v2d = &t->region->v2d; + /* Get zoom fac the same way as in + * `ui_view2d_curRect_validate_resize` - better keep in sync! */ + const float zoomx = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur); + t->zfac = 1.0f / zoomx; + } +} + void calculateCenter(TransInfo *t) { if ((t->flag & T_OVERRIDE_CENTER) == 0) { @@ -1166,22 +1194,46 @@ void calculateCenter(TransInfo *t) } } - if (t->spacetype == SPACE_VIEW3D) { - /* #ED_view3d_calc_zfac() defines a factor for perspective depth correction, - * used in #ED_view3d_win_to_delta(). */ + calculateZfac(t); +} - /* NOTE: `t->zfac` is only used #convertViewVec only in cases operator was invoked in - * #RGN_TYPE_WINDOW and never used in other cases. - * - * We need special case here as well, since #ED_view3d_calc_zfac will crash when called - * for a region different from #RGN_TYPE_WINDOW. */ - if (t->region->regiontype == RGN_TYPE_WINDOW) { - t->zfac = ED_view3d_calc_zfac(t->region->regiondata, t->center_global); +/* Called every time the view changes due to navigation. + * Adjusts the mouse position relative to the object. */ +void tranformViewUpdate(TransInfo *t) +{ + float zoom_prev = t->zfac; + float zoom_new; + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { + if (!t->persp) { + zoom_prev *= len_v3(t->persinv[0]); } - else { - t->zfac = 0.0f; + + setTransformViewMatrices(t); + calculateZfac(t); + + zoom_new = t->zfac; + if (!t->persp) { + zoom_new *= len_v3(t->persinv[0]); + } + + for (int i = 0; i < ARRAY_SIZE(t->orient); i++) { + if (t->orient[i].type == V3D_ORIENT_VIEW) { + copy_m3_m4(t->orient[i].matrix, t->viewinv); + normalize_m3(t->orient[i].matrix); + if (t->orient_curr == i) { + copy_m3_m3(t->spacemtx, t->orient[i].matrix); + invert_m3_m3_safe_ortho(t->spacemtx_inv, t->spacemtx); + } + } } } + else { + calculateZfac(t); + zoom_new = t->zfac; + } + + calculateCenter2D(t); + transform_input_update(t, zoom_prev / zoom_new); } void calculatePropRatio(TransInfo *t) @@ -1413,6 +1465,7 @@ Object *transform_object_deform_pose_armature_get(const TransInfo *t, Object *ob * Lines below just check is also visible. */ Object *ob_armature = BKE_modifiers_is_deformed_by_armature(ob); if (ob_armature && ob_armature->mode & OB_MODE_POSE) { + BKE_view_layer_synced_ensure(t->scene, t->view_layer); Base *base_arm = BKE_view_layer_base_find(t->view_layer, ob_armature); if (base_arm) { View3D *v3d = t->view; diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c index 838b40c2040..a6eb25975e9 100644 --- a/source/blender/editors/transform/transform_gizmo_2d.c +++ b/source/blender/editors/transform/transform_gizmo_2d.c @@ -236,7 +236,7 @@ static bool gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, NULL, &objects_len); + scene, view_layer, NULL, &objects_len); if (ED_uvedit_minmax_multi(scene, objects, objects_len, r_min, r_max)) { has_select = true; } @@ -247,7 +247,7 @@ static bool gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min Editing *ed = SEQ_editing_get(scene); ListBase *seqbase = SEQ_active_seqbase_get(ed); ListBase *channels = SEQ_channels_displayed_get(ed); - SeqCollection *strips = SEQ_query_rendered_strips(channels, seqbase, scene->r.cfra, 0); + SeqCollection *strips = SEQ_query_rendered_strips(scene, channels, seqbase, scene->r.cfra, 0); SEQ_filter_selected_strips(strips); int selected_strips = SEQ_collection_len(strips); if (selected_strips > 0) { @@ -299,7 +299,7 @@ static int gizmo2d_calc_transform_orientation(const bContext *C) Editing *ed = SEQ_editing_get(scene); ListBase *seqbase = SEQ_active_seqbase_get(ed); ListBase *channels = SEQ_channels_displayed_get(ed); - SeqCollection *strips = SEQ_query_rendered_strips(channels, seqbase, scene->r.cfra, 0); + SeqCollection *strips = SEQ_query_rendered_strips(scene, channels, seqbase, scene->r.cfra, 0); SEQ_filter_selected_strips(strips); bool use_local_orient = SEQ_collection_len(strips) == 1; @@ -322,7 +322,7 @@ static float gizmo2d_calc_rotation(const bContext *C) Editing *ed = SEQ_editing_get(scene); ListBase *seqbase = SEQ_active_seqbase_get(ed); ListBase *channels = SEQ_channels_displayed_get(ed); - SeqCollection *strips = SEQ_query_rendered_strips(channels, seqbase, scene->r.cfra, 0); + SeqCollection *strips = SEQ_query_rendered_strips(scene, channels, seqbase, scene->r.cfra, 0); SEQ_filter_selected_strips(strips); if (SEQ_collection_len(strips) == 1) { @@ -348,7 +348,7 @@ static bool seq_get_strip_pivot_median(const Scene *scene, float r_pivot[2]) Editing *ed = SEQ_editing_get(scene); ListBase *seqbase = SEQ_active_seqbase_get(ed); ListBase *channels = SEQ_channels_displayed_get(ed); - SeqCollection *strips = SEQ_query_rendered_strips(channels, seqbase, scene->r.cfra, 0); + SeqCollection *strips = SEQ_query_rendered_strips(scene, channels, seqbase, scene->r.cfra, 0); SEQ_filter_selected_strips(strips); bool has_select = SEQ_collection_len(strips) != 0; @@ -387,7 +387,8 @@ static bool gizmo2d_calc_transform_pivot(const bContext *C, float r_pivot[2]) Editing *ed = SEQ_editing_get(scene); ListBase *seqbase = SEQ_active_seqbase_get(ed); ListBase *channels = SEQ_channels_displayed_get(ed); - SeqCollection *strips = SEQ_query_rendered_strips(channels, seqbase, scene->r.cfra, 0); + SeqCollection *strips = SEQ_query_rendered_strips( + scene, channels, seqbase, scene->r.cfra, 0); SEQ_filter_selected_strips(strips); has_select = SEQ_collection_len(strips) != 0; SEQ_collection_free(strips); diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index 5b749e05052..8e6a6c2c411 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -639,7 +639,8 @@ int ED_transform_calc_gizmo_stats(const bContext *C, (params->orientation_index - 1) : BKE_scene_orientation_get_index(scene, SCE_ORIENT_DEFAULT); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); Object *obedit = OBEDIT_FROM_OBACT(ob); if (ob && ob->mode & OB_MODE_WEIGHT_PAINT) { Object *obpose = BKE_object_pose_armature_get(ob); @@ -753,7 +754,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, invert_m4_m4(obedit->imat, obedit->obmat); \ uint objects_len = 0; \ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( \ - view_layer, CTX_wm_view3d(C), &objects_len); \ + scene, view_layer, CTX_wm_view3d(C), &objects_len); \ for (uint ob_index = 0; ob_index < objects_len; ob_index++) { \ Object *ob_iter = objects[ob_index]; \ const bool use_mat_local = (ob_iter != obedit); @@ -941,7 +942,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, invert_m4_m4(ob->imat, ob->obmat); uint objects_len = 0; - Object **objects = BKE_object_pose_array_get(view_layer, v3d, &objects_len); + Object **objects = BKE_object_pose_array_get(scene, view_layer, v3d, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob_iter = objects[ob_index]; @@ -1014,13 +1015,14 @@ int ED_transform_calc_gizmo_stats(const bContext *C, else { /* we need the one selected object, if its not active */ - base = BASACT(view_layer); - ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + base = BKE_view_layer_active_base_get(view_layer); + ob = base ? base->object : NULL; if (base && ((base->flag & BASE_SELECTED) == 0)) { ob = NULL; } - for (base = view_layer->object_bases.first; base; base = base->next) { + for (base = BKE_view_layer_object_bases_get(view_layer)->first; base; base = base->next) { if (!BASE_SELECTED_EDITABLE(v3d, base)) { continue; } @@ -1103,7 +1105,8 @@ static void gizmo_prepare_mat(const bContext *C, /* pass */ } else { - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); if (ob != NULL) { if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) { SculptSession *ss = ob->sculpt; diff --git a/source/blender/editors/transform/transform_gizmo_extrude_3d.c b/source/blender/editors/transform/transform_gizmo_extrude_3d.c index 131a7fd517f..a3b5fd2c575 100644 --- a/source/blender/editors/transform/transform_gizmo_extrude_3d.c +++ b/source/blender/editors/transform/transform_gizmo_extrude_3d.c @@ -261,7 +261,7 @@ static void gizmo_mesh_extrude_refresh(const bContext *C, wmGizmoGroup *gzgroup) copy_m3_m3(ggd->data.normal_mat3, tbounds_normal.axis); } - /* TODO(campbell): run second since this modifies the 3D view, it should not. */ + /* TODO(@campbellbarton): run second since this modifies the 3D view, it should not. */ if (!ED_transform_calc_gizmo_stats(C, &(struct TransformCalcParams){ .orientation_index = ggd->data.orientation_index + 1, diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 3b320ff51d5..38dbe742279 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -8,6 +8,7 @@ #include <stdlib.h> #include "DNA_screen_types.h" +#include "DNA_space_types.h" #include "BKE_context.h" @@ -18,6 +19,7 @@ #include "WM_types.h" #include "transform.h" +#include "transform_mode.h" #include "MEM_guardedalloc.h" @@ -251,11 +253,8 @@ void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[ /** \name Setup & Handle Mouse Input * \{ */ -void initMouseInput(TransInfo *UNUSED(t), - MouseInput *mi, - const float center[2], - const int mval[2], - const bool precision) +void initMouseInput( + TransInfo *t, MouseInput *mi, const float center[2], const int mval[2], const bool precision) { mi->factor = 0; mi->precision = precision; @@ -266,14 +265,20 @@ void initMouseInput(TransInfo *UNUSED(t), mi->imval[0] = mval[0]; mi->imval[1] = mval[1]; + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { + float delta[3] = {mval[0] - center[0], mval[1] - center[1]}; + ED_view3d_win_to_delta(t->region, delta, t->zfac, delta); + add_v3_v3v3(mi->imval_unproj, t->center_global, delta); + } + mi->post = NULL; } static void calcSpringFactor(MouseInput *mi) { - mi->factor = sqrtf( - ((float)(mi->center[1] - mi->imval[1])) * ((float)(mi->center[1] - mi->imval[1])) + - ((float)(mi->center[0] - mi->imval[0])) * ((float)(mi->center[0] - mi->imval[0]))); + float mdir[2] = {(float)(mi->center[1] - mi->imval[1]), (float)(mi->center[0] - mi->imval[0])}; + + mi->factor = len_v2(mdir); if (mi->factor == 0.0f) { mi->factor = 1.0f; /* prevent Inf */ @@ -441,4 +446,52 @@ void applyMouseInput(TransInfo *t, MouseInput *mi, const int mval[2], float outp } } +void transform_input_update(TransInfo *t, const float fac) +{ + MouseInput *mi = &t->mouse; + t->mouse.factor *= fac; + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { + projectIntView(t, mi->imval_unproj, mi->imval); + } + else { + int offset[2], center_2d_int[2] = {mi->center[0], mi->center[1]}; + sub_v2_v2v2_int(offset, mi->imval, center_2d_int); + offset[0] *= fac; + offset[1] *= fac; + + center_2d_int[0] = t->center2d[0]; + center_2d_int[1] = t->center2d[1]; + add_v2_v2v2_int(mi->imval, center_2d_int, offset); + } + + float center_old[2]; + copy_v2_v2(center_old, mi->center); + copy_v2_v2(mi->center, t->center2d); + + if (mi->use_virtual_mval) { + /* Update accumulator. */ + double mval_delta[2]; + sub_v2_v2v2_db(mval_delta, mi->virtual_mval.accum, mi->virtual_mval.prev); + mval_delta[0] *= fac; + mval_delta[1] *= fac; + copy_v2_v2_db(mi->virtual_mval.accum, mi->virtual_mval.prev); + add_v2_v2_db(mi->virtual_mval.accum, mval_delta); + } + + if (ELEM(mi->apply, InputAngle, InputAngleSpring)) { + float offset_center[2]; + sub_v2_v2v2(offset_center, mi->center, center_old); + struct InputAngle_Data *data = mi->data; + data->mval_prev[0] += offset_center[0]; + data->mval_prev[1] += offset_center[1]; + } + + if (t->mode == TFM_EDGE_SLIDE) { + transform_mode_edge_slide_reproject_input(t); + } + else if (t->mode == TFM_VERT_SLIDE) { + transform_mode_vert_slide_reproject_input(t); + } +} + /** \} */ diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index 83f1bd35f81..10ea022757d 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -292,6 +292,9 @@ void constraintTransLim(const TransInfo *t, TransData *td) continue; } + /* Initialize the custom space for use in calculating the matrices. */ + BKE_constraint_custom_object_space_init(&cob, con); + /* get constraint targets if needed */ BKE_constraint_targets_for_solving_get(t->depsgraph, con, &cob, &targets, ctime); @@ -549,18 +552,14 @@ void ElementRotation_ex(const TransInfo *t, mul_m3_m3m3(totmat, mat, td->mtx); mul_m3_m3m3(smat, td->smtx, totmat); - /* apply gpencil falloff */ + /* Apply gpencil falloff. */ if (t->options & CTX_GPENCIL_STROKES) { bGPDstroke *gps = (bGPDstroke *)td->extra; - float sx = smat[0][0]; - float sy = smat[1][1]; - float sz = smat[2][2]; - - mul_m3_fl(smat, gps->runtime.multi_frame_falloff); - /* fix scale */ - smat[0][0] = sx; - smat[1][1] = sy; - smat[2][2] = sz; + if (gps->runtime.multi_frame_falloff != 1.0f) { + float ident_mat[3][3]; + unit_m3(ident_mat); + interp_m3_m3m3(smat, ident_mat, smat, gps->runtime.multi_frame_falloff); + } } sub_v3_v3v3(vec, td->iloc, center); @@ -945,7 +944,11 @@ void ElementResize(const TransInfo *t, if (td->ext && td->ext->size) { float fsize[3]; - if (ELEM(t->data_type, TC_SCULPT, TC_OBJECT, TC_OBJECT_TEXSPACE, TC_POSE)) { + if (ELEM(t->data_type, + &TransConvertType_Sculpt, + &TransConvertType_Object, + &TransConvertType_ObjectTexSpace, + &TransConvertType_Pose)) { float obsizemat[3][3]; /* Reorient the size mat to fit the oriented object. */ mul_m3_m3m3(obsizemat, tmat, td->axismtx); @@ -1205,13 +1208,13 @@ void transform_mode_init(TransInfo *t, wmOperator *op, const int mode) break; } - if (t->data_type == TC_MESH_VERTS) { + if (t->data_type == &TransConvertType_Mesh) { /* Init Custom Data correction. * Ideally this should be called when creating the TransData. */ transform_convert_mesh_customdatacorrect_init(t); } - /* TODO(germano): Some of these operations change the `t->mode`. + /* TODO(@germano): Some of these operations change the `t->mode`. * This can be bad for Redo. */ // BLI_assert(t->mode == mode); } diff --git a/source/blender/editors/transform/transform_mode.h b/source/blender/editors/transform/transform_mode.h index eac6734ed88..063de87ebb2 100644 --- a/source/blender/editors/transform/transform_mode.h +++ b/source/blender/editors/transform/transform_mode.h @@ -117,6 +117,7 @@ void drawEdgeSlide(TransInfo *t); void initEdgeSlide_ex( TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp); void initEdgeSlide(TransInfo *t); +void transform_mode_edge_slide_reproject_input(TransInfo *t); /* transform_mode_gpopacity.c */ @@ -191,3 +192,4 @@ void initTranslation(TransInfo *t); void drawVertSlide(TransInfo *t); void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp); void initVertSlide(TransInfo *t); +void transform_mode_vert_slide_reproject_input(TransInfo *t); diff --git a/source/blender/editors/transform/transform_mode_bend.c b/source/blender/editors/transform/transform_mode_bend.c index acc6b20810f..a48f84ef0bc 100644 --- a/source/blender/editors/transform/transform_mode_bend.c +++ b/source/blender/editors/transform/transform_mode_bend.c @@ -262,7 +262,7 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2])) +values.scale * shell_angle_to_dist((float)M_PI_2 + values.angle)); } - /* TODO(campbell): xform, compensate object center. */ + /* TODO(@campbellbarton): xform, compensate object center. */ FOREACH_TRANS_DATA_CONTAINER (t, tc) { float warp_sta_local[3]; diff --git a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c index aa4d608de04..f7f9e14b8ac 100644 --- a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c @@ -64,10 +64,8 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) if (td->val) { *td->val = td->ival * ratio; /* apply PET */ - *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); - if (*td->val <= 0.0f) { - *td->val = 0.001f; - } + *td->val = interpf(*td->val, td->ival, td->factor); + CLAMP_MIN(*td->val, 0.0f); } } } @@ -93,10 +91,6 @@ void initCurveShrinkFatten(TransInfo *t) t->num.unit_sys = t->scene->unit.system; t->num.unit_type[0] = B_UNIT_NONE; -#ifdef USE_NUM_NO_ZERO - t->num.val_flag[0] |= NUM_NO_ZERO; -#endif - t->flag |= T_NO_CONSTRAINT; } diff --git a/source/blender/editors/transform/transform_mode_edge_bevelweight.c b/source/blender/editors/transform/transform_mode_edge_bevelweight.c index 987d8396907..e96e74b596c 100644 --- a/source/blender/editors/transform/transform_mode_edge_bevelweight.c +++ b/source/blender/editors/transform/transform_mode_edge_bevelweight.c @@ -44,16 +44,11 @@ static void transdata_elem_bevel_weight(const TransInfo *UNUSED(t), TransData *td, const float weight) { - if (td->val == NULL) { + if (td->loc == NULL) { return; } - *td->val = td->ival + weight * td->factor; - if (*td->val < 0.0f) { - *td->val = 0.0f; - } - if (*td->val > 1.0f) { - *td->val = 1.0f; - } + *td->loc = td->iloc[0] + weight * td->factor; + CLAMP(*td->loc, 0.0f, 1.0f); } static void transdata_elem_bevel_weight_fn(void *__restrict iter_data_v, diff --git a/source/blender/editors/transform/transform_mode_edge_crease.c b/source/blender/editors/transform/transform_mode_edge_crease.c index f1acc2a4c9a..1a3ccf30387 100644 --- a/source/blender/editors/transform/transform_mode_edge_crease.c +++ b/source/blender/editors/transform/transform_mode_edge_crease.c @@ -44,17 +44,12 @@ static void transdata_elem_crease(const TransInfo *UNUSED(t), TransData *td, const float crease) { - if (td->val == NULL) { + if (td->loc == NULL) { return; } - *td->val = td->ival + crease * td->factor; - if (*td->val < 0.0f) { - *td->val = 0.0f; - } - if (*td->val > 1.0f) { - *td->val = 1.0f; - } + *td->loc = td->iloc[0] + crease * td->factor; + CLAMP(*td->loc, 0.0f, 1.0f); } static void transdata_elem_crease_fn(void *__restrict iter_data_v, diff --git a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c index 2327aa4e9c4..8d790b4699b 100644 --- a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c +++ b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c @@ -84,7 +84,7 @@ static void applyNormalRotation(TransInfo *t, const int UNUSED(mval[2])) transform_snap_increment(t, &angle); - applySnapping(t, &angle); + applySnappingAsGroup(t, &angle); applyNumInput(&t->num, &angle); diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c index 9a732562709..5ca1fdf75c6 100644 --- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c @@ -87,7 +87,7 @@ static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2])) } else { copy_v2_v2(values_final, t->values); - applySnapping(t, values_final); + applySnappingAsGroup(t, values_final); transform_convert_sequencer_channel_clamp(t, values_final); if (t->con.mode & CON_APPLY) { diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c index b8e9a0d1a4d..85285e38bdd 100644 --- a/source/blender/editors/transform/transform_mode_edge_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_slide.c @@ -292,6 +292,73 @@ static BMLoop *get_next_loop( return NULL; } +static void edge_slide_projmat_get(TransInfo *t, TransDataContainer *tc, float r_projectMat[4][4]) +{ + RegionView3D *rv3d = NULL; + + if (t->spacetype == SPACE_VIEW3D) { + /* Background mode support. */ + rv3d = t->region ? t->region->regiondata : NULL; + } + + if (!rv3d) { + /* Ok, let's try to survive this. */ + unit_m4(r_projectMat); + } + else { + ED_view3d_ob_project_mat_get(rv3d, tc->obedit, r_projectMat); + } +} + +static void edge_slide_pair_project(TransDataEdgeSlideVert *sv, + ARegion *region, + float projectMat[4][4], + float r_sco_a[3], + float r_sco_b[3]) +{ + BMVert *v = sv->v; + + if (sv->v_side[1]) { + ED_view3d_project_float_v3_m4(region, sv->v_side[1]->co, r_sco_b, projectMat); + } + else { + add_v3_v3v3(r_sco_b, v->co, sv->dir_side[1]); + ED_view3d_project_float_v3_m4(region, r_sco_b, r_sco_b, projectMat); + } + + if (sv->v_side[0]) { + ED_view3d_project_float_v3_m4(region, sv->v_side[0]->co, r_sco_a, projectMat); + } + else { + add_v3_v3v3(r_sco_a, v->co, sv->dir_side[0]); + ED_view3d_project_float_v3_m4(region, r_sco_a, r_sco_a, projectMat); + } +} + +static void edge_slide_data_init_mval(MouseInput *mi, EdgeSlideData *sld, float *mval_dir) +{ + /* Possible all of the edge loops are pointing directly at the view. */ + if (UNLIKELY(len_squared_v2(mval_dir) < 0.1f)) { + mval_dir[0] = 0.0f; + mval_dir[1] = 100.0f; + } + + float mval_start[2], mval_end[2]; + + /* Zero out Start. */ + zero_v2(mval_start); + + /* dir holds a vector along edge loop */ + copy_v2_v2(mval_end, mval_dir); + mul_v2_fl(mval_end, 0.5f); + + sld->mval_start[0] = mi->imval[0] + mval_start[0]; + sld->mval_start[1] = mi->imval[1] + mval_start[1]; + + sld->mval_end[0] = mi->imval[0] + mval_end[0]; + sld->mval_end[1] = mi->imval[1] + mval_end[1]; +} + /** * Calculate screenspace `mval_start` / `mval_end`, optionally slide direction. */ @@ -308,29 +375,20 @@ static void calcEdgeSlide_mval_range(TransInfo *t, BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); ARegion *region = t->region; View3D *v3d = NULL; - RegionView3D *rv3d = NULL; float projectMat[4][4]; BMBVHTree *bmbvh; /* only for use_calc_direction */ float(*loop_dir)[3] = NULL, *loop_maxdist = NULL; - float mval_start[2], mval_end[2]; float mval_dir[3], dist_best_sq; if (t->spacetype == SPACE_VIEW3D) { /* background mode support */ v3d = t->area ? t->area->spacedata.first : NULL; - rv3d = t->region ? t->region->regiondata : NULL; } - if (!rv3d) { - /* ok, let's try to survive this */ - unit_m4(projectMat); - } - else { - ED_view3d_ob_project_mat_get(rv3d, tc->obedit, projectMat); - } + edge_slide_projmat_get(t, tc, projectMat); if (use_occlude_geometry) { bmbvh = BKE_bmbvh_new_from_editmesh(em, BMBVH_RESPECT_HIDDEN, NULL, false); @@ -379,21 +437,7 @@ static void calcEdgeSlide_mval_range(TransInfo *t, continue; } - if (sv->v_side[1]) { - ED_view3d_project_float_v3_m4(region, sv->v_side[1]->co, sco_b, projectMat); - } - else { - add_v3_v3v3(sco_b, v->co, sv->dir_side[1]); - ED_view3d_project_float_v3_m4(region, sco_b, sco_b, projectMat); - } - - if (sv->v_side[0]) { - ED_view3d_project_float_v3_m4(region, sv->v_side[0]->co, sco_a, projectMat); - } - else { - add_v3_v3v3(sco_a, v->co, sv->dir_side[0]); - ED_view3d_project_float_v3_m4(region, sco_a, sco_a, projectMat); - } + edge_slide_pair_project(sv, region, projectMat, sco_a, sco_b); /* global direction */ dist_sq = dist_squared_to_line_segment_v2(mval, sco_b, sco_a); @@ -433,24 +477,7 @@ static void calcEdgeSlide_mval_range(TransInfo *t, MEM_freeN(loop_maxdist); } - /* possible all of the edge loops are pointing directly at the view */ - if (UNLIKELY(len_squared_v2(mval_dir) < 0.1f)) { - mval_dir[0] = 0.0f; - mval_dir[1] = 100.0f; - } - - /* zero out start */ - zero_v2(mval_start); - - /* dir holds a vector along edge loop */ - copy_v2_v2(mval_end, mval_dir); - mul_v2_fl(mval_end, 0.5f); - - sld->mval_start[0] = t->mval[0] + mval_start[0]; - sld->mval_start[1] = t->mval[1] + mval_start[1]; - - sld->mval_end[0] = t->mval[0] + mval_end[0]; - sld->mval_end[1] = t->mval[1] + mval_end[1]; + edge_slide_data_init_mval(&t->mouse, sld, mval_dir); if (bmbvh) { BKE_bmbvh_free(bmbvh); @@ -466,7 +493,6 @@ static void calcEdgeSlide_even(TransInfo *t, if (sld->totsv > 0) { ARegion *region = t->region; - RegionView3D *rv3d = NULL; float projectMat[4][4]; int i = 0; @@ -475,18 +501,7 @@ static void calcEdgeSlide_even(TransInfo *t, float dist_sq = 0; float dist_min_sq = FLT_MAX; - if (t->spacetype == SPACE_VIEW3D) { - /* background mode support */ - rv3d = t->region ? t->region->regiondata : NULL; - } - - if (!rv3d) { - /* ok, let's try to survive this */ - unit_m4(projectMat); - } - else { - ED_view3d_ob_project_mat_get(rv3d, tc->obedit, projectMat); - } + edge_slide_projmat_get(t, tc, projectMat); for (i = 0; i < sld->totsv; i++, sv++) { /* Set length */ @@ -1204,7 +1219,7 @@ void drawEdgeSlide(TransInfo *t) immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); immBegin(GPU_PRIM_LINES, sld->totsv * 2); - /* TODO(campbell): Loop over all verts. */ + /* TODO(@campbellbarton): Loop over all verts. */ sv = sld->sv; for (i = 0; i < sld->totsv; i++, sv++) { float a[3], b[3]; @@ -1292,7 +1307,7 @@ static void edge_slide_snap_apply(TransInfo *t, float *value) side_index = t_snap >= t_mid; } - if (t->tsnap.snapElem & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) { + if (t->tsnap.snapElem & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE_RAYCAST)) { float co_dir[3]; sub_v3_v3v3(co_dir, co_dest[side_index], co_orig); normalize_v3(co_dir); @@ -1444,7 +1459,7 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2])) final = t->values[0] + t->values_modal_offset[0]; - applySnapping(t, &final); + applySnappingAsGroup(t, &final); if (!validSnap(t)) { transform_snap_increment(t, &final); } @@ -1553,3 +1568,32 @@ void initEdgeSlide(TransInfo *t) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mouse Input Utilities + * \{ */ + +void transform_mode_edge_slide_reproject_input(TransInfo *t) +{ + ARegion *region = t->region; + + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + EdgeSlideData *sld = tc->custom.mode.data; + if (sld) { + float projectMat[4][4]; + edge_slide_projmat_get(t, tc, projectMat); + + TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + + float mval_dir[3], sco_a[3], sco_b[3]; + edge_slide_pair_project(curr_sv, region, projectMat, sco_a, sco_b); + sub_v3_v3v3(mval_dir, sco_b, sco_a); + edge_slide_data_init_mval(&t->mouse, sld, mval_dir); + } + } + + EdgeSlideData *sld = edgeSlideFirstGet(t); + setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start); +} + +/** \} */ diff --git a/source/blender/editors/transform/transform_mode_gpopacity.c b/source/blender/editors/transform/transform_mode_gpopacity.c index 83dce17d104..8b9431b65ea 100644 --- a/source/blender/editors/transform/transform_mode_gpopacity.c +++ b/source/blender/editors/transform/transform_mode_gpopacity.c @@ -74,7 +74,7 @@ static void applyGPOpacity(TransInfo *t, const int UNUSED(mval[2])) if (td->val) { *td->val = td->ival * ratio; /* apply PET */ - *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); + *td->val = interpf(*td->val, td->ival, td->factor); CLAMP(*td->val, 0.0f, 1.0f); } } diff --git a/source/blender/editors/transform/transform_mode_gpshrinkfatten.c b/source/blender/editors/transform/transform_mode_gpshrinkfatten.c index 796d5c7ae9c..d8ec7d4ff50 100644 --- a/source/blender/editors/transform/transform_mode_gpshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_gpshrinkfatten.c @@ -74,7 +74,7 @@ static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) if (td->val) { *td->val = td->ival * ratio; /* apply PET */ - *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); + *td->val = interpf(*td->val, td->ival, td->factor); if (*td->val <= 0.0f) { *td->val = 0.001f; } diff --git a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c index 19a3deade63..e2ccf61796b 100644 --- a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c @@ -90,7 +90,7 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) } /* apply PET */ - *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); + *td->val = interpf(*td->val, td->ival, td->factor); if (*td->val <= 0.0f) { *td->val = 0.001f; } diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c index ffae651e4aa..70599c3577c 100644 --- a/source/blender/editors/transform/transform_mode_resize.c +++ b/source/blender/editors/transform/transform_mode_resize.c @@ -11,6 +11,7 @@ #include "BLI_task.h" #include "BKE_context.h" +#include "BKE_image.h" #include "BKE_unit.h" #include "ED_screen.h" @@ -84,6 +85,98 @@ static void ApplySnapResize(TransInfo *t, float vec[3]) } } +/** + * Find the correction for the scaling factor when "Constrain to Bounds" is active. + * \param numerator: How far the UV boundary (unit square) is from the origin of the scale. + * \param denominator: How far the AABB is from the origin of the scale. + * \param scale: Scale parameter to update. + */ +static void constrain_scale_to_boundary(const float numerator, + const float denominator, + float *scale) +{ + if (denominator == 0.0f) { + /* The origin of the scale is on the edge of the boundary. */ + if (numerator < 0.0f) { + /* Negative scale will wrap around and put us outside the boundary. */ + *scale = 0.0f; /* Hold at the boundary instead. */ + } + return; /* Nothing else we can do without more info. */ + } + + const float correction = numerator / denominator; + if (correction < 0.0f || !isfinite(correction)) { + /* TODO: Correction is negative or invalid, but we lack context to fix `*scale`. */ + return; + } + + if (denominator < 0.0f) { + /* Scale origin is outside boundary, only make scale bigger. */ + if (*scale < correction) { + *scale = correction; + } + return; + } + + /* Scale origin is inside boundary, the "regular" case, limit maximum scale. */ + if (*scale > correction) { + *scale = correction; + } +} + +static bool clip_uv_transform_resize(TransInfo *t, float vec[2]) +{ + + /* Stores the coordinates of the closest UDIM tile. + * Also acts as an offset to the tile from the origin of UV space. */ + float base_offset[2] = {0.0f, 0.0f}; + + /* If tiled image then constrain to correct/closest UDIM tile, else 0-1 UV space. */ + const SpaceImage *sima = t->area->spacedata.first; + BKE_image_find_nearest_tile_with_offset(sima->image, t->center_global, base_offset); + + /* Assume no change is required. */ + float scale = 1.0f; + + /* Are we scaling U and V together, or just one axis? */ + const bool adjust_u = !(t->con.mode & CON_AXIS1); + const bool adjust_v = !(t->con.mode & CON_AXIS0); + const bool use_local_center = transdata_check_local_center(t, t->around); + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + for (TransData *td = tc->data; td < tc->data + tc->data_len; td++) { + + /* Get scale origin. */ + const float *scale_origin = use_local_center ? td->center : t->center_global; + + /* Alias td->loc as min and max just in case we need to optimize later. */ + const float *min = td->loc; + const float *max = td->loc; + + if (adjust_u) { + /* Update U against the left border. */ + constrain_scale_to_boundary( + scale_origin[0] - base_offset[0], scale_origin[0] - min[0], &scale); + + /* Now the right border, negated, because `-1.0 / -1.0 = 1.0` */ + constrain_scale_to_boundary( + base_offset[0] + t->aspect[0] - scale_origin[0], max[0] - scale_origin[0], &scale); + } + + /* Do the same for the V co-ordinate. */ + if (adjust_v) { + constrain_scale_to_boundary( + scale_origin[1] - base_offset[1], scale_origin[1] - min[1], &scale); + + constrain_scale_to_boundary( + base_offset[1] + t->aspect[1] - scale_origin[1], max[1] - scale_origin[1], &scale); + } + } + } + vec[0] *= scale; + vec[1] *= scale; + return scale != 1.0f; +} + static void applyResize(TransInfo *t, const int UNUSED(mval[2])) { float mat[3][3]; @@ -105,7 +198,7 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2])) constraintNumInput(t, t->values_final); } - applySnapping(t, t->values_final); + applySnappingAsGroup(t, t->values_final); } size_to_mat3(mat, t->values_final); @@ -157,7 +250,7 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2])) } /* Evil hack - redo resize if clipping needed. */ - if (t->flag & T_CLIP_UV && clipUVTransform(t, t->values_final, 1)) { + if (t->flag & T_CLIP_UV && clip_uv_transform_resize(t, t->values_final)) { size_to_mat3(mat, t->values_final); if (t->con.mode & CON_APPLY) { diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c index 94caaa288e5..f3186b21cb9 100644 --- a/source/blender/editors/transform/transform_mode_rotate.c +++ b/source/blender/editors/transform/transform_mode_rotate.c @@ -11,6 +11,7 @@ #include "BLI_task.h" #include "BKE_context.h" +#include "BKE_report.h" #include "BKE_unit.h" #include "ED_screen.h" @@ -285,9 +286,72 @@ static void applyRotationValue(TransInfo *t, } } +static bool uv_rotation_in_clip_bounds_test(const TransInfo *t, const float angle) +{ + const float cos_angle = cosf(angle); + const float sin_angle = sinf(angle); + const float *center = t->center_global; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (int i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; + } + if (td->factor < 1.0f) { + continue; /* Proportional edit, will get picked up in next phase. */ + } + + float uv[2]; + sub_v2_v2v2(uv, td->iloc, center); + float pr[2]; + pr[0] = cos_angle * uv[0] + sin_angle * uv[1]; + pr[1] = -sin_angle * uv[0] + cos_angle * uv[1]; + add_v2_v2(pr, center); + /* TODO: UDIM support. */ + if (pr[0] < 0.0f || 1.0f < pr[0]) { + return false; + } + if (pr[1] < 0.0f || 1.0f < pr[1]) { + return false; + } + } + } + return true; +} + +static bool clip_uv_transform_rotate(const TransInfo *t, float *vec, float *vec_inside_bounds) +{ + float angle = vec[0]; + if (uv_rotation_in_clip_bounds_test(t, angle)) { + vec_inside_bounds[0] = angle; /* Store for next iteration. */ + return false; /* Nothing to do. */ + } + float angle_inside_bounds = vec_inside_bounds[0]; + if (!uv_rotation_in_clip_bounds_test(t, angle_inside_bounds)) { + return false; /* No known way to fix, may as well rotate anyway. */ + } + const int max_i = 32; /* Limit iteration, mainly for debugging. */ + for (int i = 0; i < max_i; i++) { + /* Binary search. */ + const float angle_mid = (angle_inside_bounds + angle) / 2.0f; + if (angle_mid == angle_inside_bounds || angle_mid == angle) { + break; /* float precision reached. */ + } + if (uv_rotation_in_clip_bounds_test(t, angle_mid)) { + angle_inside_bounds = angle_mid; + } + else { + angle = angle_mid; + } + } + + vec_inside_bounds[0] = angle_inside_bounds; /* Store for next iteration. */ + vec[0] = angle_inside_bounds; /* Update rotation angle. */ + return true; +} + static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) { - char str[UI_MAX_DRAW_STR]; float axis_final[3]; float final = t->values[0] + t->values_modal_offset[0]; @@ -304,7 +368,7 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) final = large_rotation_limit(final); } else { - applySnapping(t, &final); + applySnappingAsGroup(t, &final); if (!(activeSnap(t) && validSnap(t))) { transform_snap_increment(t, &final); } @@ -312,13 +376,27 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) t->values_final[0] = final; - headerRotation(t, str, sizeof(str), final); - const bool is_large_rotation = hasNumInput(&t->num); applyRotationValue(t, final, axis_final, is_large_rotation); + if (t->flag & T_CLIP_UV) { + if (clip_uv_transform_rotate(t, t->values_final, t->values_inside_constraints)) { + applyRotationValue(t, t->values_final[0], axis_final, is_large_rotation); + } + + /* In proportional edit it can happen that */ + /* vertices in the radius of the brush end */ + /* outside the clipping area */ + /* XXX HACK - dg */ + if (t->flag & T_PROP_EDIT) { + clipUVData(t); + } + } + recalcData(t); + char str[UI_MAX_DRAW_STR]; + headerRotation(t, str, sizeof(str), t->values_final[0]); ED_area_status_text(t->area, str); } @@ -343,6 +421,11 @@ static void applyRotationMatrix(TransInfo *t, float mat_xform[4][4]) void initRotation(TransInfo *t) { + if (t->spacetype == SPACE_ACTION) { + BKE_report(t->reports, RPT_ERROR, "Rotation is not supported in the Dope Sheet Editor"); + t->state = TRANS_CANCEL; + } + t->mode = TFM_ROTATION; t->transform = applyRotation; t->transform_matrix = applyRotationMatrix; diff --git a/source/blender/editors/transform/transform_mode_skin_resize.c b/source/blender/editors/transform/transform_mode_skin_resize.c index 8099449ec23..bdbb66b72f4 100644 --- a/source/blender/editors/transform/transform_mode_skin_resize.c +++ b/source/blender/editors/transform/transform_mode_skin_resize.c @@ -99,7 +99,7 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2])) constraintNumInput(t, t->values_final); } - applySnapping(t, t->values_final); + applySnappingAsGroup(t, t->values_final); } size_to_mat3(mat_final, t->values_final); diff --git a/source/blender/editors/transform/transform_mode_timescale.c b/source/blender/editors/transform/transform_mode_timescale.c index 4130f6dc034..1474bc4591a 100644 --- a/source/blender/editors/transform/transform_mode_timescale.c +++ b/source/blender/editors/transform/transform_mode_timescale.c @@ -59,7 +59,7 @@ static void applyTimeScaleValue(TransInfo *t, float value) * (this is only valid when not in NLA) */ AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; - float startx = CFRA; + float startx = scene->r.cfra; float fac = value; /* take proportional editing into account */ @@ -107,7 +107,7 @@ void initTimeScale(TransInfo *t) t->mode = TFM_TIME_SCALE; t->transform = applyTimeScale; - /* recalculate center2d to use CFRA and mouse Y, since that's + /* recalculate center2d to use scene->r.cfra and mouse Y, since that's * what is used in time scale */ if ((t->flag & T_OVERRIDE_CENTER) == 0) { t->center_global[0] = t->scene->r.cfra; diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index 3c6b6ea4117..8f6ec7bd98f 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -16,6 +16,7 @@ #include "BLI_task.h" #include "BKE_context.h" +#include "BKE_image.h" #include "BKE_report.h" #include "BKE_unit.h" @@ -434,6 +435,48 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) custom_data->prev.rotate_mode = rotate_mode; } +static bool clip_uv_transform_translation(TransInfo *t, float vec[2]) +{ + /* Stores the coordinates of the closest UDIM tile. + * Also acts as an offset to the tile from the origin of UV space. */ + float base_offset[2] = {0.0f, 0.0f}; + + /* If tiled image then constrain to correct/closest UDIM tile, else 0-1 UV space. */ + const SpaceImage *sima = t->area->spacedata.first; + BKE_image_find_nearest_tile_with_offset(sima->image, t->center_global, base_offset); + + float min[2], max[2]; + min[0] = min[1] = FLT_MAX; + max[0] = max[1] = -FLT_MAX; + + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + for (TransData *td = tc->data; td < tc->data + tc->data_len; td++) { + minmax_v2v2_v2(min, max, td->loc); + } + } + + bool result = false; + if (min[0] < base_offset[0]) { + vec[0] += base_offset[0] - min[0]; + result = true; + } + else if (max[0] > base_offset[0] + t->aspect[0]) { + vec[0] -= max[0] - base_offset[0] - t->aspect[0]; + result = true; + } + + if (min[1] < base_offset[1]) { + vec[1] += base_offset[1] - min[1]; + result = true; + } + else if (max[1] > base_offset[1] + t->aspect[1]) { + vec[1] -= max[1] - base_offset[1] - t->aspect[1]; + result = true; + } + + return result; +} + static void applyTranslation(TransInfo *t, const int UNUSED(mval[2])) { char str[UI_MAX_DRAW_STR]; @@ -470,7 +513,7 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2])) } t->tsnap.snapElem = SCE_SNAP_MODE_NONE; - applySnapping(t, global_dir); + applySnappingAsGroup(t, global_dir); transform_snap_grid(t, global_dir); if (t->con.mode & CON_APPLY) { @@ -498,7 +541,7 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2])) applyTranslationValue(t, global_dir); /* evil hack - redo translation if clipping needed */ - if (t->flag & T_CLIP_UV && clipUVTransform(t, global_dir, 0)) { + if (t->flag & T_CLIP_UV && clip_uv_transform_translation(t, global_dir)) { applyTranslationValue(t, global_dir); /* In proportional edit it can happen that */ diff --git a/source/blender/editors/transform/transform_mode_vert_slide.c b/source/blender/editors/transform/transform_mode_vert_slide.c index 77c5707d814..d7c4d862b23 100644 --- a/source/blender/editors/transform/transform_mode_vert_slide.c +++ b/source/blender/editors/transform/transform_mode_vert_slide.c @@ -68,7 +68,7 @@ typedef struct VertSlideParams { bool flipped; } VertSlideParams; -static void calcVertSlideCustomPoints(struct TransInfo *t) +static void vert_slide_update_input(TransInfo *t) { VertSlideParams *slp = t->custom.mode.data; VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; @@ -94,6 +94,11 @@ static void calcVertSlideCustomPoints(struct TransInfo *t) else { setCustomPoints(t, &t->mouse, mval_end, mval_start); } +} + +static void calcVertSlideCustomPoints(struct TransInfo *t) +{ + vert_slide_update_input(t); /* setCustomPoints isn't normally changing as the mouse moves, * in this case apply mouse input immediately so we don't refresh @@ -539,7 +544,7 @@ static void vert_slide_snap_apply(TransInfo *t, float *value) getSnapPoint(t, dvec); sub_v3_v3(dvec, t->tsnap.snapTarget); - if (t->tsnap.snapElem & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) { + if (t->tsnap.snapElem & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE_RAYCAST)) { float co_dir[3]; sub_v3_v3v3(co_dir, co_curr_3d, co_orig_3d); normalize_v3(co_dir); @@ -568,7 +573,7 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2])) final = t->values[0] + t->values_modal_offset[0]; - applySnapping(t, &final); + applySnappingAsGroup(t, &final); if (!validSnap(t)) { transform_snap_increment(t, &final); } @@ -673,3 +678,22 @@ void initVertSlide(TransInfo *t) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mouse Input Utilities + * \{ */ + +void transform_mode_vert_slide_reproject_input(TransInfo *t) +{ + if (t->spacetype == SPACE_VIEW3D) { + RegionView3D *rv3d = t->region->regiondata; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + VertSlideData *sld = tc->custom.mode.data; + ED_view3d_ob_project_mat_get(rv3d, tc->obedit, sld->proj_mat); + } + } + + vert_slide_update_input(t); +} + +/** \} */ diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index cd8a2f17554..99919c0ed78 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -379,6 +379,8 @@ static int transformops_data(bContext *C, wmOperator *op, const wmEvent *event) if (op->customdata == NULL) { TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data2"); + t->undo_name = op->type->name; + int mode = transformops_mode(op); retval = initTransform(C, t, op, event, mode); @@ -566,6 +568,17 @@ static bool transform_poll_property(const bContext *UNUSED(C), } } + /* Snapping. */ + { + PropertyRNA *prop_snap = RNA_struct_find_property(op->ptr, "snap"); + if (prop_snap && (prop_snap != prop) && + (RNA_property_boolean_get(op->ptr, prop_snap) == false)) { + if (STRPREFIX(prop_id, "snap") || STRPREFIX(prop_id, "use_snap")) { + return false; + } + } + } + return true; } @@ -644,28 +657,63 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) } if (flags & P_SNAP) { - prop = RNA_def_boolean(ot->srna, "snap", 0, "Use Snapping Options", ""); + prop = RNA_def_boolean(ot->srna, "snap", false, "Use Snapping Options", ""); RNA_def_property_flag(prop, PROP_HIDDEN); + prop = RNA_def_enum(ot->srna, + "snap_elements", + rna_enum_snap_element_items, + SCE_SNAP_MODE_INCREMENT, + "Snap to Elements", + ""); + RNA_def_property_flag(prop, PROP_ENUM_FLAG); + + RNA_def_boolean(ot->srna, "use_snap_project", false, "Project Individual Elements", ""); + if (flags & P_GEO_SNAP) { - /* TODO(@gfxcoder): Rename `snap_target` to `snap_source` to avoid - * previous ambiguity of "target" (now, "source" is geometry to be moved and "target" is - * geometry to which moved geometry is snapped). Use "Source snap point" and "Point on - * source that will snap to target" for name and description, respectively. */ - prop = RNA_def_enum(ot->srna, "snap_target", rna_enum_snap_source_items, 0, "Target", ""); + /* TODO(@gfxcoder): Rename `snap_target` to `snap_source` to avoid previous ambiguity of + * "target" (now, "source" is geometry to be moved and "target" is geometry to which moved + * geometry is snapped). Use "Source snap point" and "Point on source that will snap to + * target" for name and description, respectively. */ + prop = RNA_def_enum(ot->srna, "snap_target", rna_enum_snap_source_items, 0, "Snap With", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); + + /* Target selection. */ + prop = RNA_def_boolean(ot->srna, "use_snap_self", true, "Target: Include Active", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); + prop = RNA_def_boolean(ot->srna, "use_snap_edit", true, "Target: Include Edit", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); + prop = RNA_def_boolean(ot->srna, "use_snap_nonedit", true, "Target: Include Non-Edited", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); + prop = RNA_def_boolean( + ot->srna, "use_snap_selectable_only", false, "Target: Exclude Non-Selectable", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); + + /* Face Nearest options */ + prop = RNA_def_boolean( + ot->srna, "use_snap_to_same_target", false, "Snap to Same Target", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); + prop = RNA_def_int( + ot->srna, "snap_face_nearest_steps", 1, 1, 32767, "Face Nearest Steps", "", 1, 32767); RNA_def_property_flag(prop, PROP_HIDDEN); + prop = RNA_def_float_vector( ot->srna, "snap_point", 3, NULL, -FLT_MAX, FLT_MAX, "Point", "", -FLT_MAX, FLT_MAX); RNA_def_property_flag(prop, PROP_HIDDEN); if (flags & P_ALIGN_SNAP) { - prop = RNA_def_boolean(ot->srna, "snap_align", 0, "Align with Point Normal", ""); + prop = RNA_def_boolean(ot->srna, "snap_align", false, "Align with Point Normal", ""); RNA_def_property_flag(prop, PROP_HIDDEN); prop = RNA_def_float_vector( ot->srna, "snap_normal", 3, NULL, -FLT_MAX, FLT_MAX, "Normal", "", -FLT_MAX, FLT_MAX); RNA_def_property_flag(prop, PROP_HIDDEN); } } + else { + prop = RNA_def_boolean( + ot->srna, "use_snap_selectable_only", false, "Target: Exclude Non-Selectable", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); + } } if (flags & P_GPENCIL_EDIT) { @@ -849,17 +897,6 @@ static void TRANSFORM_OT_trackball(struct wmOperatorType *ot) Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER); } -/* Similar to #transform_shear_poll. */ -static bool transform_rotate_poll(bContext *C) -{ - if (!ED_operator_screenactive(C)) { - return false; - } - - ScrArea *area = CTX_wm_area(C); - return area && !ELEM(area->spacetype, SPACE_ACTION); -} - static void TRANSFORM_OT_rotate(struct wmOperatorType *ot) { /* identifiers */ @@ -873,7 +910,7 @@ static void TRANSFORM_OT_rotate(struct wmOperatorType *ot) ot->exec = transform_exec; ot->modal = transform_modal; ot->cancel = transform_cancel; - ot->poll = transform_rotate_poll; + ot->poll = ED_operator_screenactive; ot->poll_property = transform_poll_property; RNA_def_float_rotation( @@ -938,7 +975,6 @@ static void TRANSFORM_OT_bend(struct wmOperatorType *ot) Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER); } -/* Similar to #transform_rotate_poll. */ static bool transform_shear_poll(bContext *C) { if (!ED_operator_screenactive(C)) { diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index c0d943e17ee..212df5978e4 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -476,7 +476,8 @@ void ED_transform_calc_orientation_from_type(const bContext *C, float r_mat[3][3 Object *obedit = CTX_data_edit_object(C); View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = region->regiondata; - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); const short orient_index = BKE_scene_orientation_get_index(scene, SCE_ORIENT_DEFAULT); const int pivot_point = scene->toolsettings->transform_pivot_point; @@ -515,7 +516,7 @@ short ED_transform_calc_orientation_from_type_ex(const Scene *scene, } case V3D_ORIENT_NORMAL: { if (obedit || (ob && ob->mode & OB_MODE_POSE)) { - ED_getTransformOrientationMatrix(view_layer, v3d, ob, obedit, pivot_point, r_mat); + ED_getTransformOrientationMatrix(scene, view_layer, v3d, ob, obedit, pivot_point, r_mat); break; } /* No break we define 'normal' as 'local' in Object mode. */ @@ -528,7 +529,7 @@ short ED_transform_calc_orientation_from_type_ex(const Scene *scene, * use the active pones axis for display T33575, this works as expected on a single * bone and users who select many bones will understand what's going on and what local * means when they start transforming. */ - ED_getTransformOrientationMatrix(view_layer, v3d, ob, obedit, pivot_point, r_mat); + ED_getTransformOrientationMatrix(scene, view_layer, v3d, ob, obedit, pivot_point, r_mat); } else { transform_orientations_create_from_axis(r_mat, UNPACK3(ob->obmat)); @@ -744,7 +745,8 @@ static uint bm_mesh_faces_select_get_n(BMesh *bm, BMVert **elems, const uint n) } #endif -int getTransformOrientation_ex(ViewLayer *view_layer, +int getTransformOrientation_ex(const Scene *scene, + ViewLayer *view_layer, const View3D *v3d, struct Object *ob, struct Object *obedit, @@ -1252,6 +1254,7 @@ int getTransformOrientation_ex(ViewLayer *view_layer, ok = true; } else { + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, ob); if (UNLIKELY(base == NULL)) { /* This is very unlikely, if it happens allow the value to be set since the caller @@ -1282,13 +1285,15 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3]) /* dummy value, not V3D_AROUND_ACTIVE and not V3D_AROUND_LOCAL_ORIGINS */ short around = V3D_AROUND_CENTER_BOUNDS; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); - return getTransformOrientation_ex(view_layer, v3d, obact, obedit, normal, plane, around); + return getTransformOrientation_ex(scene, view_layer, v3d, obact, obedit, normal, plane, around); } -void ED_getTransformOrientationMatrix(ViewLayer *view_layer, +void ED_getTransformOrientationMatrix(const Scene *scene, + ViewLayer *view_layer, const View3D *v3d, Object *ob, Object *obedit, @@ -1300,7 +1305,7 @@ void ED_getTransformOrientationMatrix(ViewLayer *view_layer, int type; - type = getTransformOrientation_ex(view_layer, v3d, ob, obedit, normal, plane, around); + type = getTransformOrientation_ex(scene, view_layer, v3d, ob, obedit, normal, plane, around); /* Fallback, when the plane can't be calculated. */ if (ORIENTATION_USE_PLANE(type) && is_zero_v3(plane)) { diff --git a/source/blender/editors/transform/transform_orientations.h b/source/blender/editors/transform/transform_orientations.h index 3ac235517a7..32093e830b0 100644 --- a/source/blender/editors/transform/transform_orientations.h +++ b/source/blender/editors/transform/transform_orientations.h @@ -55,7 +55,8 @@ enum { }; #define ORIENTATION_USE_PLANE(ty) ELEM(ty, ORIENTATION_NORMAL, ORIENTATION_EDGE, ORIENTATION_FACE) -int getTransformOrientation_ex(ViewLayer *view_layer, +int getTransformOrientation_ex(const Scene *scene, + ViewLayer *view_layer, const View3D *v3d, struct Object *ob, struct Object *obedit, diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 649217092aa..b47592b61cd 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -51,9 +51,6 @@ static bool doForceIncrementSnap(const TransInfo *t); -/* this should be passed as an arg for use in snap functions */ -#undef BASACT - /* use half of flt-max so we can scale up without an exception */ /* -------------------------------------------------------------------- */ @@ -126,8 +123,12 @@ bool activeSnap(const TransInfo *t) ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP_INVERT); } -bool activeSnap_with_project(const TransInfo *t) +bool activeSnap_SnappingIndividual(const TransInfo *t) { + if (activeSnap(t) && t->tsnap.mode & SCE_SNAP_MODE_FACE_NEAREST) { + return true; + } + if (!t->tsnap.project) { return false; } @@ -143,6 +144,27 @@ bool activeSnap_with_project(const TransInfo *t) return true; } +bool activeSnap_SnappingAsGroup(const TransInfo *t) +{ + if (!activeSnap(t)) { + return false; + } + + if (t->tsnap.mode == SCE_SNAP_MODE_FACE_RAYCAST && t->tsnap.project) { + return false; + } + + if (t->tsnap.mode == SCE_SNAP_MODE_FACE_NEAREST) { + return false; + } + + if (doForceIncrementSnap(t)) { + return false; + } + + return true; +} + bool transformModeUseSnap(const TransInfo *t) { ToolSettings *ts = t->settings; @@ -170,156 +192,152 @@ static bool doForceIncrementSnap(const TransInfo *t) void drawSnapping(const struct bContext *C, TransInfo *t) { uchar col[4], selectedCol[4], activeCol[4]; - if (!activeSnap(t)) { return; } - if (t->spacetype == SPACE_VIEW3D) { - bool draw_target = (t->tsnap.status & TARGET_INIT) && - (t->tsnap.mode & SCE_SNAP_MODE_EDGE_PERPENDICULAR); - - if (draw_target || validSnap(t)) { - UI_GetThemeColor3ubv(TH_TRANSFORM, col); - col[3] = 128; + bool draw_target = (t->spacetype == SPACE_VIEW3D) && (t->tsnap.status & TARGET_INIT) && + (t->tsnap.mode & SCE_SNAP_MODE_EDGE_PERPENDICULAR); - UI_GetThemeColor3ubv(TH_SELECT, selectedCol); - selectedCol[3] = 128; + if (!(draw_target || validSnap(t))) { + return; + } - UI_GetThemeColor3ubv(TH_ACTIVE, activeCol); - activeCol[3] = 192; + if (t->spacetype == SPACE_SEQ) { + UI_GetThemeColor3ubv(TH_SEQ_ACTIVE, col); + col[3] = 128; + } + else if (t->spacetype != SPACE_IMAGE) { + UI_GetThemeColor3ubv(TH_TRANSFORM, col); + col[3] = 128; - const float *loc_cur = NULL; - const float *loc_prev = NULL; - const float *normal = NULL; + UI_GetThemeColor3ubv(TH_SELECT, selectedCol); + selectedCol[3] = 128; - GPU_depth_test(GPU_DEPTH_NONE); + UI_GetThemeColor3ubv(TH_ACTIVE, activeCol); + activeCol[3] = 192; + } - RegionView3D *rv3d = CTX_wm_region_view3d(C); - if (!BLI_listbase_is_empty(&t->tsnap.points)) { - /* Draw snap points. */ + if (t->spacetype == SPACE_VIEW3D) { + const float *loc_cur = NULL; + const float *loc_prev = NULL; + const float *normal = NULL; - float size = 2.0f * UI_GetThemeValuef(TH_VERTEX_SIZE); - float view_inv[4][4]; - copy_m4_m4(view_inv, rv3d->viewinv); + GPU_depth_test(GPU_DEPTH_NONE); - uint pos = GPU_vertformat_attr_add( - immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + if (!BLI_listbase_is_empty(&t->tsnap.points)) { + /* Draw snap points. */ - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + float size = 2.0f * UI_GetThemeValuef(TH_VERTEX_SIZE); + float view_inv[4][4]; + copy_m4_m4(view_inv, rv3d->viewinv); - LISTBASE_FOREACH (TransSnapPoint *, p, &t->tsnap.points) { - if (p == t->tsnap.selectedPoint) { - immUniformColor4ubv(selectedCol); - } - else { - immUniformColor4ubv(col); - } - imm_drawcircball(p->co, ED_view3d_pixel_size(rv3d, p->co) * size, view_inv, pos); - } + uint pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immUnbindProgram(); - } + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - /* draw normal if needed */ - if (usingSnappingNormal(t) && validSnappingNormal(t)) { - normal = t->tsnap.snapNormal; + LISTBASE_FOREACH (TransSnapPoint *, p, &t->tsnap.points) { + if (p == t->tsnap.selectedPoint) { + immUniformColor4ubv(selectedCol); + } + else { + immUniformColor4ubv(col); + } + imm_drawcircball(p->co, ED_view3d_pixel_size(rv3d, p->co) * size, view_inv, pos); } - if (draw_target) { - loc_prev = t->tsnap.snapTarget; - } + immUnbindProgram(); + } - if (validSnap(t)) { - loc_cur = t->tsnap.snapPoint; - } + /* draw normal if needed */ + if (usingSnappingNormal(t) && validSnappingNormal(t)) { + normal = t->tsnap.snapNormal; + } - ED_view3d_cursor_snap_draw_util( - rv3d, loc_prev, loc_cur, normal, col, activeCol, t->tsnap.snapElem); + if (draw_target) { + loc_prev = t->tsnap.snapTarget; + } - GPU_depth_test(GPU_DEPTH_LESS_EQUAL); + if (validSnap(t)) { + loc_cur = t->tsnap.snapPoint; } + + ED_view3d_cursor_snap_draw_util( + rv3d, loc_prev, loc_cur, normal, col, activeCol, t->tsnap.snapElem); + + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } else if (t->spacetype == SPACE_IMAGE) { - if (validSnap(t)) { - uint pos = GPU_vertformat_attr_add( - immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - float x, y; - const float snap_point[2] = { - t->tsnap.snapPoint[0] / t->aspect[0], - t->tsnap.snapPoint[1] / t->aspect[1], - }; - UI_view2d_view_to_region_fl(&t->region->v2d, UNPACK2(snap_point), &x, &y); - float radius = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize; - - GPU_matrix_push_projection(); - wmOrtho2_region_pixelspace(t->region); - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformColor3ub(255, 255, 255); - imm_draw_circle_wire_2d(pos, x, y, radius, 8); - immUnbindProgram(); + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - GPU_matrix_pop_projection(); - } - } - else if (t->spacetype == SPACE_NODE) { - if (validSnap(t)) { - ARegion *region = CTX_wm_region(C); - TransSnapPoint *p; - float size; + float x, y; + const float snap_point[2] = { + t->tsnap.snapPoint[0] / t->aspect[0], + t->tsnap.snapPoint[1] / t->aspect[1], + }; + UI_view2d_view_to_region_fl(&t->region->v2d, UNPACK2(snap_point), &x, &y); + float radius = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize; - size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE); + GPU_matrix_push_projection(); + wmOrtho2_region_pixelspace(t->region); - GPU_blend(GPU_BLEND_ALPHA); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ub(255, 255, 255); + imm_draw_circle_wire_2d(pos, x, y, radius, 8); + immUnbindProgram(); - uint pos = GPU_vertformat_attr_add( - immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + GPU_matrix_pop_projection(); + } + else if (t->spacetype == SPACE_NODE) { + ARegion *region = CTX_wm_region(C); + TransSnapPoint *p; + float size; - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE); - for (p = t->tsnap.points.first; p; p = p->next) { - if (p == t->tsnap.selectedPoint) { - immUniformColor4ubv(selectedCol); - } - else { - immUniformColor4ubv(col); - } + GPU_blend(GPU_BLEND_ALPHA); - ED_node_draw_snap(®ion->v2d, p->co, size, 0, pos); - } + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - if (t->tsnap.status & POINT_INIT) { - immUniformColor4ubv(activeCol); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - ED_node_draw_snap(®ion->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder, pos); + for (p = t->tsnap.points.first; p; p = p->next) { + if (p == t->tsnap.selectedPoint) { + immUniformColor4ubv(selectedCol); + } + else { + immUniformColor4ubv(col); } - immUnbindProgram(); + ED_node_draw_snap(®ion->v2d, p->co, size, 0, pos); + } + + if (t->tsnap.status & POINT_INIT) { + immUniformColor4ubv(activeCol); - GPU_blend(GPU_BLEND_NONE); + ED_node_draw_snap(®ion->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder, pos); } + + immUnbindProgram(); + + GPU_blend(GPU_BLEND_NONE); } else if (t->spacetype == SPACE_SEQ) { - if (validSnap(t)) { - const ARegion *region = CTX_wm_region(C); - GPU_blend(GPU_BLEND_ALPHA); - uint pos = GPU_vertformat_attr_add( - immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - UI_GetThemeColor3ubv(TH_SEQ_ACTIVE, col); - col[3] = 128; - immUniformColor4ubv(col); - float pixelx = BLI_rctf_size_x(®ion->v2d.cur) / BLI_rcti_size_x(®ion->v2d.mask); - immRectf(pos, - t->tsnap.snapPoint[0] - pixelx, - region->v2d.cur.ymax, - t->tsnap.snapPoint[0] + pixelx, - region->v2d.cur.ymin); - immUnbindProgram(); - GPU_blend(GPU_BLEND_NONE); - } + const ARegion *region = CTX_wm_region(C); + GPU_blend(GPU_BLEND_ALPHA); + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4ubv(col); + float pixelx = BLI_rctf_size_x(®ion->v2d.cur) / BLI_rcti_size_x(®ion->v2d.mask); + immRectf(pos, + t->tsnap.snapPoint[0] - pixelx, + region->v2d.cur.ymax, + t->tsnap.snapPoint[0] + pixelx, + region->v2d.cur.ymin); + immUnbindProgram(); + GPU_blend(GPU_BLEND_NONE); } } @@ -343,93 +361,157 @@ eRedrawFlag handleSnapping(TransInfo *t, const wmEvent *event) return status; } -void applyProject(TransInfo *t) +static bool applyFaceProject(TransInfo *t, TransDataContainer *tc, TransData *td) { - if (!activeSnap_with_project(t)) { - return; + if (!(t->tsnap.mode & SCE_SNAP_MODE_FACE_RAYCAST)) { + return false; + } + + float iloc[3], loc[3], no[3]; + float mval_fl[2]; + + copy_v3_v3(iloc, td->loc); + if (tc->use_local_mat) { + mul_m4_v3(tc->mat, iloc); + } + else if (t->options & CTX_OBJECT) { + BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); + copy_v3_v3(iloc, td->ob->obmat[3]); + } + + if (ED_view3d_project_float_global(t->region, iloc, mval_fl, V3D_PROJ_TEST_NOP) != + V3D_PROJ_RET_OK) { + return false; + } + + eSnapMode hit = ED_transform_snap_object_project_view3d( + t->tsnap.object_context, + t->depsgraph, + t->region, + t->view, + SCE_SNAP_MODE_FACE_RAYCAST, + &(const struct SnapObjectParams){ + .snap_target_select = t->tsnap.target_select, + .edit_mode_type = (t->flag & T_EDIT) != 0 ? SNAP_GEOM_EDIT : SNAP_GEOM_FINAL, + .use_occlusion_test = false, + .use_backface_culling = t->tsnap.use_backface_culling, + }, + NULL, + mval_fl, + NULL, + 0, + loc, + no); + if (hit != SCE_SNAP_MODE_FACE_RAYCAST) { + return false; } float tvec[3]; - int i; + sub_v3_v3v3(tvec, loc, iloc); - /* XXX FLICKER IN OBJECT MODE */ - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - float iloc[3], loc[3], no[3]; - float mval_fl[2]; - if (td->flag & TD_SKIP) { - continue; - } + mul_m3_v3(td->smtx, tvec); - if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) { - continue; - } + add_v3_v3(td->loc, tvec); - copy_v3_v3(iloc, td->loc); - if (tc->use_local_mat) { - mul_m4_v3(tc->mat, iloc); - } - else if (t->options & CTX_OBJECT) { - BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); - copy_v3_v3(iloc, td->ob->obmat[3]); - } + if (t->tsnap.align && (t->options & CTX_OBJECT)) { + /* handle alignment as well */ + const float *original_normal; + float mat[3][3]; - if (ED_view3d_project_float_global(t->region, iloc, mval_fl, V3D_PROJ_TEST_NOP) == - V3D_PROJ_RET_OK) { - eSnapMode hit = ED_transform_snap_object_project_view3d( - t->tsnap.object_context, - t->depsgraph, - t->region, - t->view, - SCE_SNAP_MODE_FACE, - &(const struct SnapObjectParams){ - .snap_target_select = t->tsnap.target_select, - .edit_mode_type = (t->flag & T_EDIT) != 0 ? SNAP_GEOM_EDIT : SNAP_GEOM_FINAL, - .use_occlusion_test = false, - .use_backface_culling = t->tsnap.use_backface_culling, - }, - mval_fl, - NULL, - 0, - loc, - no); - if (hit != SCE_SNAP_MODE_FACE) { - return; - } + /* In pose mode, we want to align normals with Y axis of bones. */ + original_normal = td->axismtx[2]; -#if 0 - if (tc->use_local_mat) { - mul_m4_v3(tc->imat, loc); - } -#endif + rotation_between_vecs_to_mat3(mat, original_normal, no); - sub_v3_v3v3(tvec, loc, iloc); + transform_data_ext_rotate(td, mat, true); - mul_m3_v3(td->smtx, tvec); + /* TODO: support constraints for rotation too? see #ElementRotation. */ + } + return true; +} - add_v3_v3(td->loc, tvec); +static void applyFaceNearest(TransInfo *t, TransDataContainer *tc, TransData *td) +{ + if (!(t->tsnap.mode & SCE_SNAP_MODE_FACE_NEAREST)) { + return; + } + + float init_loc[3]; + float prev_loc[3]; + float snap_loc[3], snap_no[3]; + + copy_v3_v3(init_loc, td->iloc); + copy_v3_v3(prev_loc, td->loc); + if (tc->use_local_mat) { + mul_m4_v3(tc->mat, init_loc); + mul_m4_v3(tc->mat, prev_loc); + } + else if (t->options & CTX_OBJECT) { + BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); + copy_v3_v3(init_loc, td->ob->obmat[3]); + } - if (t->tsnap.align && (t->options & CTX_OBJECT)) { - /* handle alignment as well */ - const float *original_normal; - float mat[3][3]; + eSnapMode hit = ED_transform_snap_object_project_view3d( + t->tsnap.object_context, + t->depsgraph, + t->region, + t->view, + SCE_SNAP_MODE_FACE_NEAREST, + &(const struct SnapObjectParams){ + .snap_target_select = t->tsnap.target_select, + .edit_mode_type = (t->flag & T_EDIT) != 0 ? SNAP_GEOM_EDIT : SNAP_GEOM_FINAL, + .use_occlusion_test = false, + .use_backface_culling = false, + .face_nearest_steps = t->tsnap.face_nearest_steps, + .keep_on_same_target = t->tsnap.flag & SCE_SNAP_KEEP_ON_SAME_OBJECT, + }, + init_loc, + NULL, + prev_loc, + 0, + snap_loc, + snap_no); + + if (hit != SCE_SNAP_MODE_FACE_NEAREST) { + return; + } - /* In pose mode, we want to align normals with Y axis of bones... */ - original_normal = td->axismtx[2]; + float tvec[3]; + sub_v3_v3v3(tvec, snap_loc, prev_loc); + mul_m3_v3(td->smtx, tvec); + add_v3_v3(td->loc, tvec); - rotation_between_vecs_to_mat3(mat, original_normal, no); + /* TODO: support snap alignment similar to #SCE_SNAP_MODE_FACE_RAYCAST? */ +} - transform_data_ext_rotate(td, mat, true); +void applySnappingIndividual(TransInfo *t) +{ + if (!activeSnap_SnappingIndividual(t)) { + return; + } - /* TODO: support constraints for rotation too? see #ElementRotation. */ - } + /* XXX FLICKER IN OBJECT MODE */ + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (int i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; + } + + if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) { + continue; } - } + /* If both face ray-cast and face nearest methods are enabled, start with face ray-cast and + * fallback to face nearest ray-cast does not hit. */ + bool hit = applyFaceProject(t, tc, td); + if (!hit) { + applyFaceNearest(t, tc, td); + } #if 0 /* TODO: support this? */ - constraintTransLim(t, td); + constraintTransLim(t, td); #endif + } } } @@ -483,15 +565,9 @@ void applyGridAbsolute(TransInfo *t) } } -void applySnapping(TransInfo *t, float *vec) +void applySnappingAsGroup(TransInfo *t, float *vec) { - /* Each Trans Data already makes the snap to face */ - if (doForceIncrementSnap(t)) { - return; - } - - if (t->tsnap.project && t->tsnap.mode == SCE_SNAP_MODE_FACE) { - /* A similar snap will be applied to each transdata in `applyProject`. */ + if (!activeSnap_SnappingAsGroup(t)) { return; } @@ -644,70 +720,76 @@ static eSnapMode snap_mode_from_spacetype(TransInfo *t) return SCE_SNAP_MODE_INCREMENT; } -static eSnapTargetSelect snap_select_type_get(TransInfo *t) +static eSnapTargetSelect snap_target_select_from_spacetype(TransInfo *t) { - ViewLayer *view_layer = t->view_layer; - Base *base_act = view_layer->basact; + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Base *base_act = BKE_view_layer_active_base_get(t->view_layer); + + eSnapTargetSelect ret = SCE_SNAP_TARGET_ALL; + + bool use_snap_active = (t->tsnap.target_select & SCE_SNAP_TARGET_NOT_ACTIVE) == 0; + bool use_snap_edit = (t->tsnap.target_select & SCE_SNAP_TARGET_NOT_EDITED) == 0; + bool use_snap_nonedit = (t->tsnap.target_select & SCE_SNAP_TARGET_NOT_NONEDITED) == 0; + bool use_snap_selectable_only = (t->tsnap.target_select & SCE_SNAP_TARGET_ONLY_SELECTABLE) != 0; + if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && !(t->options & CTX_CAMERA)) { + if (base_act && (base_act->object->mode & OB_MODE_PARTICLE_EDIT)) { + /* Particles edit mode. */ + return ret; + } + + if (use_snap_selectable_only) { + ret |= SCE_SNAP_TARGET_ONLY_SELECTABLE; + } + if (t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) { /* In "Edit Strokes" mode, * snap tool can perform snap to selected or active objects (see T49632) * TODO: perform self snap in gpencil_strokes. * * When we're moving the origins, allow snapping onto our own geometry (see T69132). */ - return SCE_SNAP_TARGET_ALL; + return ret; } const int obedit_type = t->obedit_type; if (obedit_type != -1) { /* Edit mode */ - if (ELEM(obedit_type, - OB_MESH, - OB_ARMATURE, - OB_CURVES_LEGACY, - OB_SURF, - OB_LATTICE, - OB_MBALL)) { - /* Temporary limited to edit mode meshes, armature, curves, lattice and metaballs. */ - - if ((obedit_type == OB_MESH) && (t->flag & T_PROP_EDIT)) { - /* Exclude editmesh if using proportional edit */ - return SCE_SNAP_TARGET_NOT_EDITED; + if (obedit_type == OB_MESH) { + /* Editing a mesh */ + if ((t->flag & T_PROP_EDIT) != 0) { + /* Exclude editmesh when using proportional edit */ + ret |= SCE_SNAP_TARGET_NOT_EDITED; } - - if (!t->tsnap.snap_self) { - return SCE_SNAP_TARGET_NOT_ACTIVE; + if (!use_snap_active) { + ret |= SCE_SNAP_TARGET_NOT_ACTIVE; + } + if (!use_snap_edit) { + ret |= SCE_SNAP_TARGET_NOT_EDITED; + } + if (!use_snap_nonedit) { + ret |= SCE_SNAP_TARGET_NOT_NONEDITED; } - - return SCE_SNAP_TARGET_NOT_SELECTED; } - - return SCE_SNAP_TARGET_ALL; + else if (ELEM(obedit_type, OB_ARMATURE, OB_CURVES_LEGACY, OB_SURF, OB_LATTICE, OB_MBALL)) { + /* Temporary limited to edit mode armature, curves, surfaces, lattices, and metaballs. */ + ret |= SCE_SNAP_TARGET_NOT_SELECTED; + } } - - if (base_act && (base_act->object->mode & OB_MODE_PARTICLE_EDIT)) { - /* Particles edit mode. */ - return SCE_SNAP_TARGET_ALL; + else { + /* Object or pose mode. */ + ret |= SCE_SNAP_TARGET_NOT_SELECTED | SCE_SNAP_TARGET_NOT_ACTIVE; } - - /* Object or pose mode. */ - return SCE_SNAP_TARGET_NOT_SELECTED; } - - if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) { - return SCE_SNAP_TARGET_NOT_SELECTED; + else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) { + ret |= SCE_SNAP_TARGET_NOT_SELECTED; } - return SCE_SNAP_TARGET_ALL; + return ret; } static void initSnappingMode(TransInfo *t) { - ToolSettings *ts = t->settings; - t->tsnap.mode = snap_mode_from_spacetype(t); - t->tsnap.target_select = snap_select_type_get(t); - - if ((t->spacetype != SPACE_VIEW3D) || !(ts->snap_mode & SCE_SNAP_MODE_FACE)) { + if ((t->spacetype != SPACE_VIEW3D) || !(t->tsnap.mode & SCE_SNAP_MODE_FACE_RAYCAST)) { /* Force project off when not supported. */ t->tsnap.project = false; } @@ -724,7 +806,7 @@ static void initSnappingMode(TransInfo *t) t->tsnap.use_backface_culling = snap_use_backface_culling(t); t->tsnap.object_context = ED_transform_snap_object_context_create(t->scene, 0); - if (t->data_type == TC_MESH_VERTS) { + if (t->data_type == &TransConvertType_Mesh) { /* Ignore elements being transformed. */ ED_transform_snap_object_context_set_editmesh_callbacks( t->tsnap.object_context, @@ -753,9 +835,14 @@ static void initSnappingMode(TransInfo *t) void initSnapping(TransInfo *t, wmOperator *op) { + ToolSettings *ts = t->settings; + eSnapSourceSelect snap_source = ts->snap_target; + resetSnapping(t); + t->tsnap.mode = snap_mode_from_spacetype(t); t->tsnap.flag = snap_flag_from_spacetype(t); - eSnapSourceSelect snap_source = t->settings->snap_target; + t->tsnap.target_select = snap_target_select_from_spacetype(t); + t->tsnap.face_nearest_steps = max_ii(ts->snap_face_nearest_steps, 1); /* if snap property exists */ PropertyRNA *prop; @@ -764,11 +851,16 @@ void initSnapping(TransInfo *t, wmOperator *op) if (RNA_property_boolean_get(op->ptr, prop)) { t->modifiers |= MOD_SNAP; + if ((prop = RNA_struct_find_property(op->ptr, "snap_elements")) && + RNA_property_is_set(op->ptr, prop)) { + t->tsnap.mode = RNA_property_enum_get(op->ptr, prop); + } + + /* TODO(@gfxcoder): Rename `snap_target` to `snap_source` to avoid previous ambiguity of + * "target" (now, "source" is geometry to be moved and "target" is geometry to which moved + * geometry is snapped). */ if ((prop = RNA_struct_find_property(op->ptr, "snap_target")) && RNA_property_is_set(op->ptr, prop)) { - /* TODO(@gfxcoder): Rename `snap_target` to `snap_source` to avoid - * previous ambiguity of "target" (now, "source" is geometry to be moved and "target" is - * geometry to which moved geometry is snapped). */ snap_source = RNA_property_enum_get(op->ptr, prop); } @@ -791,9 +883,33 @@ void initSnapping(TransInfo *t, wmOperator *op) t->tsnap.project = RNA_property_boolean_get(op->ptr, prop); } + /* use_snap_self is misnamed and should be use_snap_active */ if ((prop = RNA_struct_find_property(op->ptr, "use_snap_self")) && RNA_property_is_set(op->ptr, prop)) { - t->tsnap.snap_self = RNA_property_boolean_get(op->ptr, prop); + SET_FLAG_FROM_TEST(t->tsnap.target_select, + !RNA_property_boolean_get(op->ptr, prop), + SCE_SNAP_TARGET_NOT_ACTIVE); + } + + if ((prop = RNA_struct_find_property(op->ptr, "use_snap_edit")) && + RNA_property_is_set(op->ptr, prop)) { + SET_FLAG_FROM_TEST(t->tsnap.target_select, + !RNA_property_boolean_get(op->ptr, prop), + SCE_SNAP_TARGET_NOT_EDITED); + } + + if ((prop = RNA_struct_find_property(op->ptr, "use_snap_nonedit")) && + RNA_property_is_set(op->ptr, prop)) { + SET_FLAG_FROM_TEST(t->tsnap.target_select, + !RNA_property_boolean_get(op->ptr, prop), + SCE_SNAP_TARGET_NOT_NONEDITED); + } + + if ((prop = RNA_struct_find_property(op->ptr, "use_snap_selectable")) && + RNA_property_is_set(op->ptr, prop)) { + SET_FLAG_FROM_TEST(t->tsnap.target_select, + RNA_property_boolean_get(op->ptr, prop), + SCE_SNAP_TARGET_ONLY_SELECTABLE); } } } @@ -805,8 +921,19 @@ void initSnapping(TransInfo *t, wmOperator *op) t->tsnap.align = ((t->tsnap.flag & SCE_SNAP_ROTATE) != 0); t->tsnap.project = ((t->tsnap.flag & SCE_SNAP_PROJECT) != 0); - t->tsnap.snap_self = !((t->tsnap.flag & SCE_SNAP_NO_SELF) != 0); t->tsnap.peel = ((t->tsnap.flag & SCE_SNAP_PROJECT) != 0); + SET_FLAG_FROM_TEST(t->tsnap.target_select, + (ts->snap_flag & SCE_SNAP_NOT_TO_ACTIVE), + SCE_SNAP_TARGET_NOT_ACTIVE); + SET_FLAG_FROM_TEST(t->tsnap.target_select, + !(ts->snap_flag & SCE_SNAP_TO_INCLUDE_EDITED), + SCE_SNAP_TARGET_NOT_EDITED); + SET_FLAG_FROM_TEST(t->tsnap.target_select, + !(ts->snap_flag & SCE_SNAP_TO_INCLUDE_NONEDITED), + SCE_SNAP_TARGET_NOT_NONEDITED); + SET_FLAG_FROM_TEST(t->tsnap.target_select, + (ts->snap_flag & SCE_SNAP_TO_ONLY_SELECTABLE), + SCE_SNAP_TARGET_ONLY_SELECTABLE); } t->tsnap.source_select = snap_source; @@ -833,7 +960,8 @@ static void setSnappingCallback(TransInfo *t) } else if (t->spacetype == SPACE_IMAGE) { SpaceImage *sima = t->area->spacedata.first; - Object *obact = t->view_layer->basact ? t->view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *obact = BKE_view_layer_active_object_get(t->view_layer); const bool is_uv_editor = sima->mode == SI_MODE_UV; const bool has_edit_object = obact && BKE_object_is_in_editmode(obact); @@ -991,8 +1119,8 @@ static void snap_calc_view3d_fn(TransInfo *t, float *UNUSED(vec)) found = (snap_elem != SCE_SNAP_MODE_NONE); } if ((found == false) && (t->tsnap.mode & SCE_SNAP_MODE_VOLUME)) { - found = peelObjectsTransform( - t, mval, (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0, loc, no, NULL); + bool use_peel = (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0; + found = peelObjectsTransform(t, mval, use_peel, loc, no, NULL); if (found) { snap_elem = SCE_SNAP_MODE_VOLUME; @@ -1018,7 +1146,7 @@ static void snap_calc_uv_fn(TransInfo *t, float *UNUSED(vec)) if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) { uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - t->view_layer, NULL, &objects_len); + t->scene, t->view_layer, NULL, &objects_len); float dist_sq = square_f((float)SNAP_MIN_DISTANCE); if (ED_uvedit_nearest_uv_multi(&t->region->v2d, @@ -1026,7 +1154,7 @@ static void snap_calc_uv_fn(TransInfo *t, float *UNUSED(vec)) objects, objects_len, t->mval, - t->tsnap.target_select == SCE_SNAP_TARGET_NOT_SELECTED, + t->tsnap.target_select & SCE_SNAP_TARGET_NOT_SELECTED, &dist_sq, t->tsnap.snapPoint)) { t->tsnap.snapPoint[0] *= t->aspect[0]; @@ -1118,7 +1246,7 @@ static void snap_target_grid_ensure(TransInfo *t) { /* Only need to calculate once. */ if ((t->tsnap.status & TARGET_GRID_INIT) == 0) { - if (t->data_type == TC_CURSOR_VIEW3D) { + if (t->data_type == &TransConvertType_Cursor3D) { /* Use a fallback when transforming the cursor. * In this case the center is _not_ derived from the cursor which is being transformed. */ copy_v3_v3(t->tsnap.snapTargetGrid, TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->data->iloc); @@ -1321,9 +1449,10 @@ eSnapMode snapObjectsTransform( &(const struct SnapObjectParams){ .snap_target_select = t->tsnap.target_select, .edit_mode_type = (t->flag & T_EDIT) != 0 ? SNAP_GEOM_EDIT : SNAP_GEOM_FINAL, - .use_occlusion_test = t->settings->snap_mode != SCE_SNAP_MODE_FACE, + .use_occlusion_test = t->settings->snap_mode != SCE_SNAP_MODE_FACE_RAYCAST, .use_backface_culling = t->tsnap.use_backface_culling, }, + NULL, mval, target, dist_px, @@ -1423,7 +1552,7 @@ bool peelObjectsTransform(TransInfo *t, static bool snapNodeTest(View2D *v2d, bNode *node, eSnapTargetSelect snap_target_select) { /* node is use for snapping only if a) snap mode matches and b) node is inside the view */ - return ((snap_target_select == SCE_SNAP_TARGET_NOT_SELECTED && !(node->flag & NODE_SELECT)) || + return (((snap_target_select & SCE_SNAP_TARGET_NOT_SELECTED) && !(node->flag & NODE_SELECT)) || (snap_target_select == SCE_SNAP_TARGET_ALL && !(node->flag & NODE_ACTIVE))) && (node->totr.xmin < v2d->cur.xmax && node->totr.xmax > v2d->cur.xmin && node->totr.ymin < v2d->cur.ymax && node->totr.ymax > v2d->cur.ymin); diff --git a/source/blender/editors/transform/transform_snap.h b/source/blender/editors/transform/transform_snap.h index 6db027df067..3672e76c778 100644 --- a/source/blender/editors/transform/transform_snap.h +++ b/source/blender/editors/transform/transform_snap.h @@ -40,15 +40,16 @@ float transform_snap_increment_get(const TransInfo *t); bool transform_snap_grid(TransInfo *t, float *val); bool activeSnap(const TransInfo *t); -bool activeSnap_with_project(const TransInfo *t); +bool activeSnap_SnappingIndividual(const TransInfo *t); +bool activeSnap_SnappingAsGroup(const TransInfo *t); bool validSnap(const TransInfo *t); void initSnapping(struct TransInfo *t, struct wmOperator *op); void freeSnapping(struct TransInfo *t); -void applyProject(TransInfo *t); +void applySnappingIndividual(TransInfo *t); void applyGridAbsolute(TransInfo *t); -void applySnapping(TransInfo *t, float *vec); +void applySnappingAsGroup(TransInfo *t, float *vec); void resetSnapping(TransInfo *t); eRedrawFlag handleSnapping(TransInfo *t, const struct wmEvent *event); void drawSnapping(const struct bContext *C, TransInfo *t); diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index cf99d4b2ef3..503452b312e 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -47,6 +47,7 @@ using blender::float3; using blender::float4x4; using blender::Map; +using blender::Span; /* -------------------------------------------------------------------- */ /** \name Internal Data Types @@ -243,6 +244,11 @@ static SnapData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, SnapData_Mesh *sod; bool init = false; + const Span<MVert> verts = me_eval->verts(); + const Span<MEdge> edges = me_eval->edges(); + const Span<MPoly> polys = me_eval->polys(); + const Span<MLoop> loops = me_eval->loops(); + if (std::unique_ptr<SnapData_Mesh> *sod_p = sctx->mesh_caches.lookup_ptr(ob_eval)) { sod = sod_p->get(); bool is_dirty = false; @@ -264,16 +270,16 @@ static SnapData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, else if (sod->treedata_mesh.looptri != me_eval->runtime.looptris.array) { is_dirty = true; } - else if (sod->treedata_mesh.vert != me_eval->mvert) { + else if (sod->treedata_mesh.vert != verts.data()) { is_dirty = true; } - else if (sod->treedata_mesh.loop != me_eval->mloop) { + else if (sod->treedata_mesh.loop != loops.data()) { is_dirty = true; } - else if (sod->treedata_mesh.edge != me_eval->medge) { + else if (sod->treedata_mesh.edge != edges.data()) { is_dirty = true; } - else if (sod->poly != me_eval->mpoly) { + else if (sod->poly != polys.data()) { is_dirty = true; } @@ -303,16 +309,16 @@ static SnapData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, use_hide ? BVHTREE_FROM_LOOPTRI_NO_HIDDEN : BVHTREE_FROM_LOOPTRI, 4); - BLI_assert(sod->treedata_mesh.vert == me_eval->mvert); - BLI_assert(!me_eval->mvert || sod->treedata_mesh.vert_normals); - BLI_assert(sod->treedata_mesh.loop == me_eval->mloop); - BLI_assert(!me_eval->mpoly || sod->treedata_mesh.looptri); + BLI_assert(sod->treedata_mesh.vert == verts.data()); + BLI_assert(!verts.data() || sod->treedata_mesh.vert_normals); + BLI_assert(sod->treedata_mesh.loop == loops.data()); + BLI_assert(!polys.data() || sod->treedata_mesh.looptri); sod->has_looptris = sod->treedata_mesh.tree != nullptr; /* Required for snapping with occlusion. */ - sod->treedata_mesh.edge = me_eval->medge; - sod->poly = me_eval->mpoly; + sod->treedata_mesh.edge = edges.data(); + sod->poly = polys.data(); /* Start assuming that it has each of these element types. */ sod->has_loose_edge = true; @@ -405,6 +411,62 @@ static SnapData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx, return sod; } +static BVHTreeFromMesh *snap_object_data_mesh_treedata_get(SnapObjectContext *sctx, + Object *ob_eval, + const Mesh *me_eval, + bool use_hide) +{ + SnapData_Mesh *sod = snap_object_data_mesh_get(sctx, ob_eval, me_eval, use_hide); + return &sod->treedata_mesh; +} + +static BVHTreeFromEditMesh *snap_object_data_editmesh_treedata_get(SnapObjectContext *sctx, + Object *ob_eval, + BMEditMesh *em) +{ + SnapData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob_eval, em); + + BVHTreeFromEditMesh *treedata = &sod->treedata_editmesh; + + if (treedata->tree == nullptr) { + /* Operators only update the editmesh looptris of the original mesh. */ + BLI_assert(sod->treedata_editmesh.em == + BKE_editmesh_from_object(DEG_get_original_object(ob_eval))); + em = sod->treedata_editmesh.em; + + if (sctx->callbacks.edit_mesh.test_face_fn) { + BMesh *bm = em->bm; + BLI_assert(poly_to_tri_count(bm->totface, bm->totloop) == em->tottri); + + BLI_bitmap *elem_mask = BLI_BITMAP_NEW(em->tottri, __func__); + int looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( + bm, + elem_mask, + sctx->callbacks.edit_mesh.test_face_fn, + sctx->callbacks.edit_mesh.user_data); + + bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6); + + MEM_freeN(elem_mask); + } + else { + /* Only cache if BVH-tree is created without a mask. + * This helps keep a standardized BVH-tree in cache. */ + BKE_bvhtree_from_editmesh_get(treedata, + em, + 4, + BVHTREE_FROM_EM_LOOPTRI, + &sod->mesh_runtime->bvh_cache, + static_cast<ThreadMutex *>(sod->mesh_runtime->eval_mutex)); + } + } + if (treedata == nullptr || treedata->tree == nullptr) { + return nullptr; + } + + return treedata; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -419,16 +481,16 @@ using IterSnapObjsCallback = void (*)(SnapObjectContext *sctx, void *data); static bool snap_object_is_snappable(const SnapObjectContext *sctx, - const eSnapTargetSelect snap_select, + const eSnapTargetSelect snap_target_select, const Base *base_act, - const Base *base, - const bool is_in_object_mode) + const Base *base) { if (!BASE_VISIBLE(sctx->runtime.v3d, base)) { return false; } - if ((snap_select == SCE_SNAP_TARGET_ALL) || (base->flag_legacy & BA_TRANSFORM_LOCKED_IN_PLACE)) { + if ((snap_target_select == SCE_SNAP_TARGET_ALL) || + (base->flag_legacy & BA_TRANSFORM_LOCKED_IN_PLACE)) { return true; } @@ -436,25 +498,38 @@ static bool snap_object_is_snappable(const SnapObjectContext *sctx, return false; } - if (snap_select == SCE_SNAP_TARGET_NOT_ACTIVE) { - return base_act != base; - } + /* Get attributes of potential target. */ + const bool is_active = (base_act == base); + const bool is_selected = (base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL); + const bool is_edited = (base->object->mode == OB_MODE_EDIT); + const bool is_selectable = (base->flag & BASE_SELECTABLE); + /* Get attributes of state. */ + const bool is_in_object_mode = (base_act == nullptr) || + (base_act->object->mode == OB_MODE_OBJECT); - if (snap_select == SCE_SNAP_TARGET_NOT_EDITED) { - return base->object->mode != OB_MODE_EDIT; + if (is_in_object_mode) { + /* Handle target selection options that make sense for object mode. */ + if ((snap_target_select & SCE_SNAP_TARGET_NOT_SELECTED) && is_selected) { + /* What is selectable or not is part of the object and depends on the mode. */ + return false; + } } - - if (snap_select == SCE_SNAP_TARGET_NOT_SELECTED) { - if (is_in_object_mode) { - return !((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)); + else { + /* Handle target selection options that make sense for edit/pose mode. */ + if ((snap_target_select & SCE_SNAP_TARGET_NOT_ACTIVE) && is_active) { + return false; + } + if ((snap_target_select & SCE_SNAP_TARGET_NOT_EDITED) && is_edited && !is_active) { + /* Base is edited, but not active. */ + return false; + } + if ((snap_target_select & SCE_SNAP_TARGET_NOT_NONEDITED) && !is_edited) { + return false; } - - /* What is selectable or not is part of the object and depends on the mode. */ - return true; } - if (snap_select == SCE_SNAP_TARGET_ONLY_SELECTABLE) { - return (base->flag & BASE_SELECTABLE) != 0; + if ((snap_target_select & SCE_SNAP_TARGET_ONLY_SELECTABLE) && !is_selectable) { + return false; } return true; @@ -468,13 +543,14 @@ static void iter_snap_objects(SnapObjectContext *sctx, IterSnapObjsCallback sob_callback, void *data) { + Scene *scene = DEG_get_input_scene(sctx->runtime.depsgraph); ViewLayer *view_layer = DEG_get_input_view_layer(sctx->runtime.depsgraph); const eSnapTargetSelect snap_target_select = params->snap_target_select; + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base_act = BKE_view_layer_active_base_get(view_layer); - Base *base_act = view_layer->basact; - const bool is_in_object_mode = !base_act || base_act->object->mode == OB_MODE_OBJECT; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { - if (!snap_object_is_snappable(sctx, snap_target_select, base_act, base, is_in_object_mode)) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { + if (!snap_object_is_snappable(sctx, snap_target_select, base_act, base)) { continue; } @@ -850,40 +926,9 @@ static bool raycastEditMesh(SnapObjectContext *sctx, len_diff = 0.0f; } - BVHTreeFromEditMesh *treedata = &sod->treedata_editmesh; - - if (treedata->tree == nullptr) { - em = sod->treedata_editmesh.em; - - if (sctx->callbacks.edit_mesh.test_face_fn) { - BMesh *bm = em->bm; - BLI_assert(poly_to_tri_count(bm->totface, bm->totloop) == em->tottri); - - BLI_bitmap *elem_mask = BLI_BITMAP_NEW(em->tottri, __func__); - int looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( - bm, - elem_mask, - sctx->callbacks.edit_mesh.test_face_fn, - sctx->callbacks.edit_mesh.user_data); - - bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6); - - MEM_freeN(elem_mask); - } - else { - /* Only cache if bvhtree is created without a mask. - * This helps keep a standardized bvhtree in cache. */ - BKE_bvhtree_from_editmesh_get(treedata, - em, - 4, - BVHTREE_FROM_EM_LOOPTRI, - &sod->mesh_runtime->bvh_cache, - static_cast<ThreadMutex *>(sod->mesh_runtime->eval_mutex)); - } - - if (treedata->tree == nullptr) { - return retval; - } + BVHTreeFromEditMesh *treedata = snap_object_data_editmesh_treedata_get(sctx, ob_eval, em); + if (treedata == nullptr) { + return retval; } float timat[3][3]; /* transpose inverse matrix for normals */ @@ -1098,7 +1143,7 @@ static void raycast_obj_fn(SnapObjectContext *sctx, * \param r_loc: Hit location. * \param r_no: Hit normal (optional). * \param r_index: Hit index or -1 when no valid index is found. - * (currently only set to the polygon index when using `snap_to == SCE_SNAP_MODE_FACE`). + * (currently only set to the polygon index when using `snap_to == SCE_SNAP_MODE_FACE_RAYCAST`). * \param r_ob: Hit object. * \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances). * \param r_hit_list: List of #SnapObjectHitDepth (caller must free). @@ -1150,6 +1195,324 @@ static bool raycastObjects(SnapObjectContext *sctx, /** \} */ /* -------------------------------------------------------------------- */ +/** \name Surface Snap Funcs + * \{ */ + +struct NearestWorldObjUserData { + const float *init_co; + const float *curr_co; + /* return args */ + float *r_loc; + float *r_no; + int *r_index; + float r_dist_sq; + Object **r_ob; + float (*r_obmat)[4]; + ListBase *r_hit_list; + bool ret; +}; + +static void nearest_world_tree_co(BVHTree *tree, + BVHTree_NearestPointCallback nearest_cb, + void *treedata, + float co[3], + float r_co[3], + float r_no[3], + int *r_index, + float *r_dist_sq) +{ + BVHTreeNearest nearest = {}; + nearest.index = -1; + copy_v3_fl(nearest.co, FLT_MAX); + nearest.dist_sq = FLT_MAX; + + BLI_bvhtree_find_nearest(tree, co, &nearest, nearest_cb, treedata); + + if (r_co) { + copy_v3_v3(r_co, nearest.co); + } + if (r_no) { + copy_v3_v3(r_no, nearest.no); + } + if (r_index) { + *r_index = nearest.index; + } + if (r_dist_sq) { + float diff[3]; + sub_v3_v3v3(diff, co, nearest.co); + *r_dist_sq = len_squared_v3(diff); + } +} + +static bool nearest_world_tree(SnapObjectContext *UNUSED(sctx), + const struct SnapObjectParams *params, + BVHTree *tree, + BVHTree_NearestPointCallback nearest_cb, + void *treedata, + const float (*obmat)[4], + const float init_co[3], + const float curr_co[3], + float *r_dist_sq, + float *r_loc, + float *r_no, + int *r_index) +{ + if (curr_co == nullptr || init_co == nullptr) { + /* No location to work with, so just return. */ + return false; + } + + float imat[4][4]; + invert_m4_m4(imat, obmat); + + float timat[3][3]; /* transpose inverse matrix for normals */ + transpose_m3_m4(timat, imat); + + /* compute offset between init co and prev co in local space */ + float init_co_local[3], curr_co_local[3]; + float delta_local[3]; + mul_v3_m4v3(init_co_local, imat, init_co); + mul_v3_m4v3(curr_co_local, imat, curr_co); + sub_v3_v3v3(delta_local, curr_co_local, init_co_local); + + float dist_sq; + if (params->keep_on_same_target) { + nearest_world_tree_co( + tree, nearest_cb, treedata, init_co_local, nullptr, nullptr, nullptr, &dist_sq); + } + else { + /* NOTE: when `params->face_nearest_steps == 1`, the return variables of function below contain + * the answer. We could return immediately after updating r_loc, r_no, r_index, but that would + * also complicate the code. Foregoing slight optimization for code clarity. */ + nearest_world_tree_co( + tree, nearest_cb, treedata, curr_co_local, nullptr, nullptr, nullptr, &dist_sq); + } + if (*r_dist_sq <= dist_sq) { + return false; + } + *r_dist_sq = dist_sq; + + /* scale to make `snap_face_nearest_steps` steps */ + float step_scale_factor = 1.0f / max_ff(1.0f, (float)params->face_nearest_steps); + mul_v3_fl(delta_local, step_scale_factor); + + float co_local[3]; + float no_local[3]; + int index; + + copy_v3_v3(co_local, init_co_local); + + for (int i = 0; i < params->face_nearest_steps; i++) { + add_v3_v3(co_local, delta_local); + nearest_world_tree_co( + tree, nearest_cb, treedata, co_local, co_local, no_local, &index, nullptr); + } + + mul_v3_m4v3(r_loc, obmat, co_local); + + if (r_no) { + mul_v3_m3v3(r_no, timat, no_local); + normalize_v3(r_no); + } + + if (r_index) { + *r_index = index; + } + + return true; +} + +static bool nearest_world_mesh(SnapObjectContext *sctx, + const struct SnapObjectParams *params, + Object *ob_eval, + const Mesh *me_eval, + const float (*obmat)[4], + bool use_hide, + const float init_co[3], + const float curr_co[3], + float *r_dist_sq, + float *r_loc, + float *r_no, + int *r_index) +{ + BVHTreeFromMesh *treedata = snap_object_data_mesh_treedata_get(sctx, ob_eval, me_eval, use_hide); + if (treedata == nullptr || treedata->tree == nullptr) { + return false; + } + + return nearest_world_tree(sctx, + params, + treedata->tree, + treedata->nearest_callback, + treedata, + obmat, + init_co, + curr_co, + r_dist_sq, + r_loc, + r_no, + r_index); +} + +static bool nearest_world_editmesh(SnapObjectContext *sctx, + const struct SnapObjectParams *params, + Object *ob_eval, + BMEditMesh *em, + const float (*obmat)[4], + const float init_co[3], + const float curr_co[3], + float *r_dist_sq, + float *r_loc, + float *r_no, + int *r_index) +{ + BVHTreeFromEditMesh *treedata = snap_object_data_editmesh_treedata_get(sctx, ob_eval, em); + if (treedata == nullptr || treedata->tree == nullptr) { + return false; + } + + return nearest_world_tree(sctx, + params, + treedata->tree, + treedata->nearest_callback, + treedata, + obmat, + init_co, + curr_co, + r_dist_sq, + r_loc, + r_no, + r_index); +} +static void nearest_world_object_fn(SnapObjectContext *sctx, + const struct SnapObjectParams *params, + Object *ob_eval, + const float obmat[4][4], + bool is_object_active, + void *data) +{ + struct NearestWorldObjUserData *dt = static_cast<NearestWorldObjUserData *>(data); + + bool retval = false; + switch (ob_eval->type) { + case OB_MESH: { + const eSnapEditType edit_mode_type = params->edit_mode_type; + bool use_hide = false; + const Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide); + if (me_eval) { + retval = nearest_world_mesh(sctx, + params, + ob_eval, + me_eval, + obmat, + use_hide, + dt->init_co, + dt->curr_co, + &dt->r_dist_sq, + dt->r_loc, + dt->r_no, + dt->r_index); + } + else { + BMEditMesh *em = BKE_editmesh_from_object(ob_eval); + BLI_assert_msg(em == BKE_editmesh_from_object(DEG_get_original_object(ob_eval)), + "Make sure there is only one pointer for looptris"); + retval = nearest_world_editmesh(sctx, + params, + ob_eval, + em, + obmat, + dt->init_co, + dt->curr_co, + &dt->r_dist_sq, + dt->r_loc, + dt->r_no, + dt->r_index); + } + break; + } + case OB_CURVES_LEGACY: + case OB_SURF: + case OB_FONT: + if (!is_object_active) { + const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); + if (me_eval) { + retval = nearest_world_mesh(sctx, + params, + ob_eval, + me_eval, + obmat, + false, + dt->init_co, + dt->curr_co, + &dt->r_dist_sq, + dt->r_loc, + dt->r_no, + dt->r_index); + } + } + break; + } + + if (retval) { + if (dt->r_ob) { + *dt->r_ob = ob_eval; + } + if (dt->r_obmat) { + copy_m4_m4(dt->r_obmat, obmat); + } + dt->ret = true; + } +} + +/** + * Main Nearest World Surface Function + * =================================== + * + * Walks through all objects in the scene to find the nearest location on target surface. + * + * \param sctx: Snap context to store data. + * \param params: Settings for snapping. + * \param init_co: Initial location of source point. + * \param prev_co: Current location of source point after transformation but before snapping. + * + * Output Args + * ----------- + * + * \param r_loc: Location of nearest point on target surface. + * \param r_no: Normal of nearest point on target surface. + * \param r_index: Index of nearest polygon on target surface. + * \param r_ob: Nearest target object. + * \param r_obmat: Nearest target matrix (may not be #Object.obmat with dupli-instances). + */ +static bool nearestWorldObjects(SnapObjectContext *sctx, + const struct SnapObjectParams *params, + const float init_co[3], + const float curr_co[3], + float *r_loc /* NOLINT */, + float *r_no /* NOLINT */, + int *r_index /* NOLINT */, + Object **r_ob, + float r_obmat[4][4]) +{ + NearestWorldObjUserData data = {}; + data.init_co = init_co; + data.curr_co = curr_co; + data.r_loc = r_loc; + data.r_no = r_no; + data.r_index = r_index; + data.r_dist_sq = FLT_MAX; + data.r_ob = r_ob; + data.r_obmat = r_obmat; + data.ret = false; + + iter_snap_objects(sctx, params, nearest_world_object_fn, &data); + return data.ret; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Snap Nearest utilities * \{ */ @@ -1842,7 +2205,8 @@ static eSnapMode snapArmature(SnapObjectContext *sctx, { eSnapMode retval = SCE_SNAP_MODE_NONE; - if (sctx->runtime.snap_to_flag == SCE_SNAP_MODE_FACE) { /* Currently only edge and vert */ + if (sctx->runtime.snap_to_flag == SCE_SNAP_MODE_FACE_RAYCAST) { + /* Currently only edge and vert */ return retval; } @@ -2268,7 +2632,7 @@ static eSnapMode snapCamera(const SnapObjectContext *sctx, if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) { BKE_tracking_camera_get_reconstructed_interpolate( - tracking, tracking_object, CFRA, reconstructed_camera_mat); + tracking, tracking_object, scene->r.cfra, reconstructed_camera_mat); invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat); } @@ -2328,7 +2692,7 @@ static eSnapMode snapMesh(SnapObjectContext *sctx, float r_no[3], int *r_index) { - BLI_assert(sctx->runtime.snap_to_flag != SCE_SNAP_MODE_FACE); + BLI_assert(sctx->runtime.snap_to_flag != SCE_SNAP_MODE_FACE_RAYCAST); if (me_eval->totvert == 0) { return SCE_SNAP_MODE_NONE; } @@ -2506,9 +2870,9 @@ static eSnapMode snapEditMesh(SnapObjectContext *sctx, float r_no[3], int *r_index) { - BLI_assert(sctx->runtime.snap_to_flag != SCE_SNAP_MODE_FACE); + BLI_assert(sctx->runtime.snap_to_flag != SCE_SNAP_MODE_FACE_RAYCAST); - if ((sctx->runtime.snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_VERTEX) { + if ((sctx->runtime.snap_to_flag & ~SCE_SNAP_MODE_FACE_RAYCAST) == SCE_SNAP_MODE_VERTEX) { if (em->bm->totvert == 0) { return SCE_SNAP_MODE_NONE; } @@ -2811,7 +3175,7 @@ static void snap_obj_fn(SnapObjectContext *sctx, * \param r_loc: Hit location. * \param r_no: Hit normal (optional). * \param r_index: Hit index or -1 when no valid index is found. - * (currently only set to the polygon index when using `snap_to == SCE_SNAP_MODE_FACE`). + * (currently only set to the polygon index when using `snap_to == SCE_SNAP_MODE_FACE_RAYCAST`). * \param r_ob: Hit object. * \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances). */ @@ -3014,6 +3378,7 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont const View3D *v3d, const eSnapMode snap_to_flag, const SnapObjectParams *params, + const float init_co[3], const float mval[2], const float prev_co[3], float *dist_px, @@ -3045,11 +3410,36 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont bool use_occlusion_test = params->use_occlusion_test && !XRAY_ENABLED(v3d); - if (snap_to_flag & SCE_SNAP_MODE_FACE || use_occlusion_test) { + /* NOTE: if both face ray-cast and face nearest are enabled, first find result of nearest, then + * override with ray-cast. */ + if ((snap_to_flag & SCE_SNAP_MODE_FACE_NEAREST) && !has_hit) { + has_hit = nearestWorldObjects( + sctx, params, init_co, prev_co, loc, no, &index, &ob_eval, obmat); + + if (has_hit) { + retval = SCE_SNAP_MODE_FACE_NEAREST; + + copy_v3_v3(r_loc, loc); + if (r_no) { + copy_v3_v3(r_no, no); + } + if (r_ob) { + *r_ob = ob_eval; + } + if (r_obmat) { + copy_m4_m4(r_obmat, obmat); + } + if (r_index) { + *r_index = index; + } + } + } + + if (snap_to_flag & SCE_SNAP_MODE_FACE_RAYCAST || use_occlusion_test) { float ray_start[3], ray_normal[3]; if (!ED_view3d_win_to_ray_clipped_ex( depsgraph, region, v3d, mval, nullptr, ray_normal, ray_start, true)) { - return SCE_SNAP_MODE_NONE; + return retval; } float dummy_ray_depth = BVH_RAYCAST_DIST_MAX; @@ -3071,8 +3461,8 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont copy_v3_v3(r_face_nor, no); } - if ((snap_to_flag & SCE_SNAP_MODE_FACE)) { - retval = SCE_SNAP_MODE_FACE; + if ((snap_to_flag & SCE_SNAP_MODE_FACE_RAYCAST)) { + retval = SCE_SNAP_MODE_FACE_RAYCAST; copy_v3_v3(r_loc, loc); if (r_no) { @@ -3179,10 +3569,6 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont if (r_index) { *r_index = index; } - if (r_face_nor && !has_hit) { - /* Fallback. */ - copy_v3_v3(r_face_nor, no); - } *dist_px = dist_px_tmp; } @@ -3197,6 +3583,7 @@ eSnapMode ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, const View3D *v3d, const eSnapMode snap_to, const SnapObjectParams *params, + const float init_co[3], const float mval[2], const float prev_co[3], float *dist_px, @@ -3213,6 +3600,7 @@ eSnapMode ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, v3d, snap_to, params, + init_co, mval, prev_co, dist_px, @@ -3230,6 +3618,7 @@ eSnapMode ED_transform_snap_object_project_view3d(SnapObjectContext *sctx, const View3D *v3d, const eSnapMode snap_to, const SnapObjectParams *params, + const float init_co[3], const float mval[2], const float prev_co[3], float *dist_px, @@ -3242,6 +3631,7 @@ eSnapMode ED_transform_snap_object_project_view3d(SnapObjectContext *sctx, v3d, snap_to, params, + init_co, mval, prev_co, dist_px, diff --git a/source/blender/editors/transform/transform_snap_sequencer.c b/source/blender/editors/transform/transform_snap_sequencer.c index dbcae2b6320..06d9bb05206 100644 --- a/source/blender/editors/transform/transform_snap_sequencer.c +++ b/source/blender/editors/transform/transform_snap_sequencer.c @@ -28,6 +28,7 @@ #include "SEQ_time.h" #include "transform.h" +#include "transform_convert.h" #include "transform_snap.h" typedef struct TransSeqSnapData { @@ -59,21 +60,23 @@ static int cmp_fn(const void *a, const void *b) return (*(int *)a - *(int *)b); } -static void seq_snap_source_points_build(TransSeqSnapData *snap_data, SeqCollection *snap_sources) +static void seq_snap_source_points_build(const Scene *scene, + TransSeqSnapData *snap_data, + SeqCollection *snap_sources) { int i = 0; Sequence *seq; SEQ_ITERATOR_FOREACH (seq, snap_sources) { int left = 0, right = 0; if (seq->flag & SEQ_LEFTSEL) { - left = right = SEQ_time_left_handle_frame_get(seq); + left = right = SEQ_time_left_handle_frame_get(scene, seq); } else if (seq->flag & SEQ_RIGHTSEL) { - left = right = SEQ_time_right_handle_frame_get(seq); + left = right = SEQ_time_right_handle_frame_get(scene, seq); } else { - left = SEQ_time_left_handle_frame_get(seq); - right = SEQ_time_right_handle_frame_get(seq); + left = SEQ_time_left_handle_frame_get(scene, seq); + right = SEQ_time_right_handle_frame_get(scene, seq); } snap_data->source_snap_points[i] = left; @@ -92,7 +95,8 @@ static void seq_snap_source_points_build(TransSeqSnapData *snap_data, SeqCollect * \{ */ /* Add effect strips directly or indirectly connected to `seq_reference` to `collection`. */ -static void query_strip_effects_fn(Sequence *seq_reference, +static void query_strip_effects_fn(const Scene *scene, + Sequence *seq_reference, ListBase *seqbase, SeqCollection *collection) { @@ -103,7 +107,7 @@ static void query_strip_effects_fn(Sequence *seq_reference, /* Find all strips connected to `seq_reference`. */ LISTBASE_FOREACH (Sequence *, seq_test, seqbase) { if (SEQ_relation_is_effect_of_strip(seq_test, seq_reference)) { - query_strip_effects_fn(seq_test, seqbase, collection); + query_strip_effects_fn(scene, seq_test, seqbase, collection); } } } @@ -145,7 +149,7 @@ static SeqCollection *query_snap_targets(Scene *scene, /* Effects will always change position with strip to which they are connected and they don't have * to be selected. Remove such strips from `snap_targets` collection. */ SeqCollection *snap_sources_temp = SEQ_collection_duplicate(snap_sources); - SEQ_collection_expand(seqbase, snap_sources_temp, query_strip_effects_fn); + SEQ_collection_expand(scene, seqbase, snap_sources_temp, query_strip_effects_fn); SeqCollection *snap_sources_effects = seq_collection_extract_effects(snap_sources_temp); SEQ_collection_exclude(snap_targets, snap_sources_effects); SEQ_collection_free(snap_sources_temp); @@ -188,30 +192,31 @@ static void seq_snap_target_points_build(Scene *scene, int i = 0; if (snap_mode & SEQ_SNAP_TO_CURRENT_FRAME) { - snap_data->target_snap_points[i] = CFRA; + snap_data->target_snap_points[i] = scene->r.cfra; i++; } Sequence *seq; SEQ_ITERATOR_FOREACH (seq, snap_targets) { - snap_data->target_snap_points[i] = SEQ_time_left_handle_frame_get(seq); - snap_data->target_snap_points[i + 1] = SEQ_time_right_handle_frame_get(seq); + snap_data->target_snap_points[i] = SEQ_time_left_handle_frame_get(scene, seq); + snap_data->target_snap_points[i + 1] = SEQ_time_right_handle_frame_get(scene, seq); i += 2; if (snap_mode & SEQ_SNAP_TO_STRIP_HOLD) { - int content_start = min_ii(SEQ_time_right_handle_frame_get(seq), seq->start); - int content_end = max_ii(SEQ_time_left_handle_frame_get(seq), seq->start + seq->len); + int content_start = min_ii(SEQ_time_right_handle_frame_get(scene, seq), seq->start); + int content_end = max_ii(SEQ_time_left_handle_frame_get(scene, seq), seq->start + seq->len); /* Effects and single image strips produce incorrect content length. Skip these strips. */ if ((seq->type & SEQ_TYPE_EFFECT) != 0 || seq->len == 1) { - content_start = SEQ_time_left_handle_frame_get(seq); - content_end = SEQ_time_right_handle_frame_get(seq); + content_start = SEQ_time_left_handle_frame_get(scene, seq); + content_end = SEQ_time_right_handle_frame_get(scene, seq); } CLAMP(content_start, - SEQ_time_left_handle_frame_get(seq), - SEQ_time_right_handle_frame_get(seq)); - CLAMP( - content_end, SEQ_time_left_handle_frame_get(seq), SEQ_time_right_handle_frame_get(seq)); + SEQ_time_left_handle_frame_get(scene, seq), + SEQ_time_right_handle_frame_get(scene, seq)); + CLAMP(content_end, + SEQ_time_left_handle_frame_get(scene, seq), + SEQ_time_right_handle_frame_get(scene, seq)); snap_data->target_snap_points[i] = content_start; snap_data->target_snap_points[i + 1] = content_end; @@ -240,7 +245,7 @@ static int seq_snap_threshold_get_frame_distance(const TransInfo *t) TransSeqSnapData *transform_snap_sequencer_data_alloc(const TransInfo *t) { - if (t->data_type == TC_SEQ_IMAGE_DATA) { + if (t->data_type == &TransConvertType_SequencerImage) { return NULL; } @@ -260,7 +265,7 @@ TransSeqSnapData *transform_snap_sequencer_data_alloc(const TransInfo *t) /* Build arrays of snap points. */ seq_snap_source_points_alloc(snap_data, snap_sources); - seq_snap_source_points_build(snap_data, snap_sources); + seq_snap_source_points_build(scene, snap_data, snap_sources); SEQ_collection_free(snap_sources); short snap_mode = t->tsnap.mode; @@ -371,7 +376,7 @@ bool ED_transform_snap_sequencer_to_closest_strip_calc(Scene *scene, t.scene = scene; t.region = region; t.values[0] = 0; - t.data_type = TC_SEQ_DATA; + t.data_type = &TransConvertType_Sequencer; t.tsnap.mode = SEQ_tool_settings_snap_mode_get(scene); *r_snap_distance = transform_snap_sequencer_to_closest_strip_ex(&t, frame_1, frame_2); |