diff options
-rw-r--r-- | release/scripts/startup/bl_ui/properties_constraint.py | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/constraint.c | 57 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_convert.c | 8 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_constraint_types.h | 35 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_constraint.c | 49 |
5 files changed, 134 insertions, 17 deletions
diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py index df53fccf9ea..dce2d2f2758 100644 --- a/release/scripts/startup/bl_ui/properties_constraint.py +++ b/release/scripts/startup/bl_ui/properties_constraint.py @@ -761,6 +761,8 @@ class ConstraintButtonsPanel: sub.prop(con, "to_min_z" + ext, text="Min") sub.prop(con, "to_max_z" + ext, text="Max") + layout.prop(con, "mix_mode" + ext, text="Mix") + self.space_template(layout, con) def SHRINKWRAP(self, _context, layout, con): diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 58011c8d753..9b32996aa96 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -3802,7 +3802,8 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t /* only evaluate if there is a target */ if (VALID_CONS_TARGET(ct)) { float *from_min, *from_max, *to_min, *to_max; - float loc[3], eul[3], size[3]; + float loc[3], rot[3][3], oldeul[3], size[3]; + float newloc[3], newrot[3][3], neweul[3], newsize[3]; float dbuf[4], sval[3]; float *const dvec = dbuf + 1; int i; @@ -3844,9 +3845,7 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t } /* extract components of owner's matrix */ - copy_v3_v3(loc, cob->matrix[3]); - mat4_to_eulO(eul, rot_order, cob->matrix); - mat4_to_size(size, cob->matrix); + mat4_to_loc_rot_size(loc, rot, size, cob->matrix); /* determine where in range current transforms lie */ if (data->expo) { @@ -3878,18 +3877,42 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t to_min = data->to_min_scale; to_max = data->to_max_scale; for (i = 0; i < 3; i++) { - /* multiply with original scale (so that it can still be scaled) */ - /* size[i] *= to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i])); */ - /* Stay absolute, else it breaks existing rigs... sigh. */ - size[i] = to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i])); + newsize[i] = to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i])); + } + switch (data->mix_mode_scale) { + case TRANS_MIXSCALE_MULTIPLY: + mul_v3_v3(size, newsize); + break; + case TRANS_MIXSCALE_REPLACE: + default: + copy_v3_v3(size, newsize); + break; } break; case TRANS_ROTATION: to_min = data->to_min_rot; to_max = data->to_max_rot; for (i = 0; i < 3; i++) { - /* add to original rotation (so that it can still be rotated) */ - eul[i] += to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i])); + neweul[i] = to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i])); + } + switch (data->mix_mode_rot) { + case TRANS_MIXROT_REPLACE: + eulO_to_mat3(rot, neweul, rot_order); + break; + case TRANS_MIXROT_BEFORE: + eulO_to_mat3(newrot, neweul, rot_order); + mul_m3_m3m3(rot, newrot, rot); + break; + case TRANS_MIXROT_AFTER: + eulO_to_mat3(newrot, neweul, rot_order); + mul_m3_m3m3(rot, rot, newrot); + break; + case TRANS_MIXROT_ADD: + default: + mat3_to_eulO(oldeul, rot_order, rot); + add_v3_v3(neweul, oldeul); + eulO_to_mat3(rot, neweul, rot_order); + break; } break; case TRANS_LOCATION: @@ -3897,14 +3920,22 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t to_min = data->to_min; to_max = data->to_max; for (i = 0; i < 3; i++) { - /* add to original location (so that it can still be moved) */ - loc[i] += (to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i]))); + newloc[i] = (to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i]))); + } + switch (data->mix_mode_loc) { + case TRANS_MIXLOC_REPLACE: + copy_v3_v3(loc, newloc); + break; + case TRANS_MIXLOC_ADD: + default: + add_v3_v3(loc, newloc); + break; } break; } /* apply to matrix */ - loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, rot_order); + loc_rot_size_to_mat4(cob->matrix, loc, rot, size); } } diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index cbb291414bf..6da03d917a6 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -1348,11 +1348,13 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list) /* Transform constraint needs it for rotation at least (r.57309), * but doing so when translating may also mess things up [#36203] */ + bTransformConstraint *data = (bTransformConstraint *)con->data; - if (t->mode == TFM_ROTATION) { - return true; + if (data->to == TRANS_ROTATION) { + if (t->mode == TFM_ROTATION && data->mix_mode_rot == TRANS_MIXROT_BEFORE) { + return true; + } } - /* ??? (t->mode == TFM_SCALE) ? */ } } } diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index d123cf21db9..83fc4d2a3f7 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -450,7 +450,12 @@ typedef struct bTransformConstraint { /** Output euler order override. */ char to_euler_order; - char _pad[6]; + /** Mixing modes for location, rotation, and scale. */ + char mix_mode_loc; + char mix_mode_rot; + char mix_mode_scale; + + char _pad[3]; /** From_min/max defines range of target transform. */ float from_min[3]; @@ -809,6 +814,34 @@ typedef enum eTransform_ToFrom { TRANS_SCALE = 2, } eTransform_ToFrom; +/* bTransformConstraint.mix_mode_loc */ +typedef enum eTransform_MixModeLoc { + /* Add component values together (default). */ + TRANS_MIXLOC_ADD = 0, + /* Replace component values. */ + TRANS_MIXLOC_REPLACE, +} eTransform_MixModeLoc; + +/* bTransformConstraint.mix_mode_rot */ +typedef enum eTransform_MixModeRot { + /* Add component values together (default). */ + TRANS_MIXROT_ADD = 0, + /* Replace component values. */ + TRANS_MIXROT_REPLACE, + /* Multiply the generated rotation on the left. */ + TRANS_MIXROT_BEFORE, + /* Multiply the generated rotation on the right. */ + TRANS_MIXROT_AFTER, +} eTransform_MixModeRot; + +/* bTransformConstraint.mix_mode_scale */ +typedef enum eTransform_MixModeScale { + /* Replace component values (default). */ + TRANS_MIXSCALE_REPLACE = 0, + /* Multiply component values together. */ + TRANS_MIXSCALE_MULTIPLY, +} eTransform_MixModeScale; + /* bSameVolumeConstraint.free_axis */ typedef enum eSameVolume_Axis { SAMEVOL_X = 0, diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 658addece8a..7732bf531d8 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -1934,6 +1934,34 @@ static void rna_def_constraint_transform(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem mix_mode_loc_items[] = { + {TRANS_MIXLOC_REPLACE, "REPLACE", 0, "Replace", "Replace component values"}, + {TRANS_MIXLOC_ADD, "ADD", 0, "Add", "Add component values together"}, + {0, NULL, 0, NULL, NULL}, + }; + + static const EnumPropertyItem mix_mode_rot_items[] = { + {TRANS_MIXROT_REPLACE, "REPLACE", 0, "Replace", "Replace component values"}, + {TRANS_MIXROT_ADD, "ADD", 0, "Add", "Add component values together"}, + {TRANS_MIXROT_BEFORE, + "BEFORE", + 0, + "Before Original", + "Apply new rotation before original, as if it was on a parent"}, + {TRANS_MIXROT_AFTER, + "AFTER", + 0, + "After Original", + "Apply new rotation after original, as if it was on a child"}, + {0, NULL, 0, NULL, NULL}, + }; + + static const EnumPropertyItem mix_mode_scale_items[] = { + {TRANS_MIXSCALE_REPLACE, "REPLACE", 0, "Replace", "Replace component values"}, + {TRANS_MIXSCALE_MULTIPLY, "MULTIPLY", 0, "Multiply", "Multiply component values together"}, + {0, NULL, 0, NULL, NULL}, + }; + srna = RNA_def_struct(brna, "TransformConstraint", "Constraint"); RNA_def_struct_ui_text( srna, "Transformation Constraint", "Map transformations of the target to the object"); @@ -2066,6 +2094,13 @@ static void rna_def_constraint_transform(BlenderRNA *brna) RNA_def_property_ui_text(prop, "To Maximum Z", "Top range of Z axis destination motion"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + prop = RNA_def_property(srna, "mix_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mix_mode_loc"); + RNA_def_property_enum_items(prop, mix_mode_loc_items); + RNA_def_property_ui_text( + prop, "Location Mix Mode", "Specify how to combine the new location with original"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + /* Rot */ prop = RNA_def_property(srna, "from_min_x_rot", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "from_min_rot[0]"); @@ -2139,6 +2174,13 @@ static void rna_def_constraint_transform(BlenderRNA *brna) RNA_def_property_ui_text(prop, "To Maximum Z", "Top range of Z axis destination motion"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + prop = RNA_def_property(srna, "mix_mode_rot", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mix_mode_rot"); + RNA_def_property_enum_items(prop, mix_mode_rot_items); + RNA_def_property_ui_text( + prop, "Rotation Mix Mode", "Specify how to combine the new rotation with original"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + /* Scale */ prop = RNA_def_property(srna, "from_min_x_scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "from_min_scale[0]"); @@ -2211,6 +2253,13 @@ static void rna_def_constraint_transform(BlenderRNA *brna) RNA_def_property_ui_range(prop, -1000.0f, 1000.0f, 10, 3); RNA_def_property_ui_text(prop, "To Maximum Z", "Top range of Z axis destination motion"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + prop = RNA_def_property(srna, "mix_mode_scale", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mix_mode_scale"); + RNA_def_property_enum_items(prop, mix_mode_scale_items); + RNA_def_property_ui_text( + prop, "Scale Mix Mode", "Specify how to combine the new scale with original"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); } static void rna_def_constraint_location_limit(BlenderRNA *brna) |