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/intern/object.c | 34 ++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel/intern') 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; -- cgit v1.2.3