From 39f3474cf138c8245c0cb6faa314971dd465c6e7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 6 Sep 2019 20:00:45 +1000 Subject: Fix T69536: Setting dimensions for parented objects fails Parenting/constraints/delta-scaled all caused setting dimensions to fail. Take the difference between the input scale and final scale into account when applying the dimensions. --- source/blender/blenkernel/BKE_object.h | 6 ++++ source/blender/blenkernel/intern/object.c | 34 +++++++++++++++++++++- .../blender/editors/space_view3d/view3d_buttons.c | 7 ++++- 3 files changed, 45 insertions(+), 2 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index cf4bce3a209..5162e1cf51d 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -222,7 +222,13 @@ void BKE_boundbox_minmax(const struct BoundBox *bb, struct BoundBox *BKE_object_boundbox_get(struct Object *ob); void BKE_object_dimensions_get(struct Object *ob, float vec[3]); +void BKE_object_dimensions_set_ex(struct Object *ob, + const float value[3], + int axis_mask, + const float ob_scale_orig[3], + const float ob_obmat_orig[4][4]); void BKE_object_dimensions_set(struct Object *ob, const float value[3], int axis_mask); + void BKE_object_empty_draw_type_set(struct Object *ob, const int value); void BKE_object_boundbox_flag(struct Object *ob, int flag, const bool set); void BKE_object_boundbox_calc_from_mesh(struct Object *ob, struct Mesh *me_eval); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index ed517bfc513..acfa6085d45 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2799,6 +2799,12 @@ void BKE_object_boundbox_calc_from_mesh(struct Object *ob, struct Mesh *me_eval) ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY; } +/* -------------------------------------------------------------------- */ +/** \name Object Dimension Get/Set + * + * \warning Setting dimensions is prone to feedback loops in evaluation. + * \{ */ + void BKE_object_dimensions_get(Object *ob, float vec[3]) { BoundBox *bb = NULL; @@ -2818,7 +2824,19 @@ void BKE_object_dimensions_get(Object *ob, float vec[3]) } } -void BKE_object_dimensions_set(Object *ob, const float value[3], int axis_mask) +/** + * The original scale and object matrix can be passed in so any difference + * of the objects matrix and the final matrix can be accounted for, + * typically this caused by parenting, constraints or delta-scale. + * + * Re-using these values from the object causes a feedback loop + * when multiple values are modified at once in some situations. see: T69536. + */ +void BKE_object_dimensions_set_ex(Object *ob, + const float value[3], + int axis_mask, + const float ob_scale_orig[3], + const float ob_obmat_orig[4][4]) { BoundBox *bb = NULL; @@ -2832,7 +2850,16 @@ void BKE_object_dimensions_set(Object *ob, const float value[3], int axis_mask) for (int i = 0; i < 3; i++) { if (((1 << i) & axis_mask) == 0) { + + if (ob_scale_orig != NULL) { + const float scale_delta = len_v3(ob_obmat_orig[i]) / ob_scale_orig[i]; + if (isfinite(scale_delta)) { + len[i] *= scale_delta; + } + } + if (len[i] > 0.0f) { + ob->scale[i] = copysignf(value[i] / len[i], ob->scale[i]); } } @@ -2840,6 +2867,11 @@ void BKE_object_dimensions_set(Object *ob, const float value[3], int axis_mask) } } +void BKE_object_dimensions_set(Object *ob, const float value[3], int axis_mask) +{ + BKE_object_dimensions_set_ex(ob, value, axis_mask, NULL, NULL); +} + void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool use_hidden) { BoundBox bb; diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 3d3c73ad27c..1ace1198795 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -106,7 +106,9 @@ typedef union { /* temporary struct for storing transform properties */ typedef struct { + float ob_obmat_orig[4][4]; float ob_dims_orig[3]; + float ob_scale_orig[3]; float ob_dims[3]; /* Floats only (treated as an array). */ TransformMedian ve_median, median; @@ -1050,6 +1052,8 @@ static void v3d_object_dimension_buts(bContext *C, uiLayout *layout, View3D *v3d BKE_object_dimensions_get(ob, tfp->ob_dims); copy_v3_v3(tfp->ob_dims_orig, tfp->ob_dims); + copy_v3_v3(tfp->ob_scale_orig, ob->scale); + copy_m4_m4(tfp->ob_obmat_orig, ob->obmat); uiDefBut(block, UI_BTYPE_LABEL, @@ -1095,7 +1099,8 @@ static void v3d_object_dimension_buts(bContext *C, uiLayout *layout, View3D *v3d axis_mask |= (1 << i); } } - BKE_object_dimensions_set(ob, tfp->ob_dims, axis_mask); + BKE_object_dimensions_set_ex( + ob, tfp->ob_dims, axis_mask, tfp->ob_scale_orig, tfp->ob_obmat_orig); PointerRNA obptr; RNA_id_pointer_create(&ob->id, &obptr); -- cgit v1.2.3