Copy Scale: support raising the copied scale to an arbitrary power.
authorAlexander Gavrilov <angavrilov@gmail.com>
Wed, 8 May 2019 09:08:54 +0000 (12:08 +0300)
committerAlexander Gavrilov <angavrilov@gmail.com>
Wed, 8 May 2019 09:17:00 +0000 (12:17 +0300)
Since scale is multiplicative, the appropriate way to partially copy
it is to use power. However, the influence slider of constraints uses
linear interpolation. Thus, there is no way to correctly split scale
via constraints without adding this feature.

In addition, this allows inverting scale by using negative powers,
fulfilling the function of Copy Rotation's Invert checkboxes.

release/scripts/startup/bl_ui/properties_constraint.py
source/blender/blenkernel/intern/constraint.c
source/blender/blenloader/intern/versioning_280.c
source/blender/makesdna/DNA_constraint_types.h
source/blender/makesrna/intern/rna_constraint.c

index 310d35c61793a99eac6beff7de20a7143f17f7bd..c972ce04cdf9e7a28a91b862aed1985572b85f21 100644 (file)
@@ -430,6 +430,8 @@ class ConstraintButtonsPanel:
         row.prop(con, "use_y", text="Y")
         row.prop(con, "use_z", text="Z")
 
+        layout.prop(con, "power")
+
         row = layout.row()
         row.prop(con, "use_offset")
         row = row.row()
index 2ccfcf45e46bc3ef5b6daeda3c2594af7ff30e3a..218dfbd7b148afd0f114aa83d17bfe098d7bb12c 100644 (file)
@@ -1882,6 +1882,7 @@ static void sizelike_new_data(void *cdata)
   bSizeLikeConstraint *data = (bSizeLikeConstraint *)cdata;
 
   data->flag = SIZELIKE_X | SIZELIKE_Y | SIZELIKE_Z | SIZELIKE_MULTIPLY;
+  data->power = 1.0f;
 }
 
 static void sizelike_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
@@ -1929,6 +1930,10 @@ static void sizelike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *ta
     mat4_to_size(size, ct->matrix);
     mat4_to_size(obsize, cob->matrix);
 
+    for (int i = 0; i < 3; i++) {
+      size[i] = powf(size[i], data->power);
+    }
+
     if (data->flag & SIZELIKE_OFFSET) {
       /* Scale is a multiplicative quantity, so adding it makes no sense.
        * However, the additive mode has to stay for backward compatibility. */
index 194459a1edade62a7a84b7f9287cd9f9dba1a8c3..b2e171108d866debc781b048013d8d844c94384b 100644 (file)
@@ -702,6 +702,16 @@ static void do_version_constraints_maintain_volume_mode_uniform(ListBase *lb)
   }
 }
 
+static void do_version_constraints_copy_scale_power(ListBase *lb)
+{
+  for (bConstraint *con = lb->first; con; con = con->next) {
+    if (con->type == CONSTRAINT_TYPE_SIZELIKE) {
+      bSizeLikeConstraint *data = (bSizeLikeConstraint *)con->data;
+      data->power = 1.0f;
+    }
+  }
+}
+
 void do_versions_after_linking_280(Main *bmain)
 {
   bool use_collection_compat_28 = true;
@@ -3348,6 +3358,18 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
   }
 
   {
+    /* Added a power option to Copy Scale. */
+    if (!DNA_struct_elem_find(fd->filesdna, "bSizeLikeConstraint", "float", "power")) {
+      LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+        do_version_constraints_copy_scale_power(&ob->constraints);
+        if (ob->pose) {
+          LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+            do_version_constraints_copy_scale_power(&pchan->constraints);
+          }
+        }
+      }
+    }
+
     /* Versioning code until next subversion bump goes here. */
   }
 }
index 3abd5b4456e15d7c4d87bcdac282d637dfcc9e48..c09ea400f4c0cec98fbbf122dd0ff8bfa19c9984 100644 (file)
@@ -289,7 +289,7 @@ typedef struct bLocateLikeConstraint {
 typedef struct bSizeLikeConstraint {
   struct Object *tar;
   int flag;
-  int reserved1;
+  float power;
   /** MAX_ID_NAME-2. */
   char subtarget[64];
 } bSizeLikeConstraint;
index ef3ea19fa5736109b6efdf4ff5cbec3c8fe3586b..41ad94f61194139ac5714f9059156137399dd5b9 100644 (file)
@@ -1327,6 +1327,13 @@ static void rna_def_constraint_size_like(BlenderRNA *brna)
   RNA_def_property_ui_text(prop, "Copy Z", "Copy the target's Z scale");
   RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
 
+  prop = RNA_def_property(srna, "power", PROP_FLOAT, PROP_NONE);
+  RNA_def_property_float_sdna(prop, NULL, "power");
+  RNA_def_property_float_default(prop, 1.0f);
+  RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 3);
+  RNA_def_property_ui_text(prop, "Power", "Raise the target's scale to the specified power");
+  RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
   prop = RNA_def_property(srna, "use_offset", PROP_BOOLEAN, PROP_NONE);
   RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_OFFSET);
   RNA_def_property_ui_text(prop, "Offset", "Combine original scale with copied scale");