Fix T39897: shape keys created while the Relative checkbox is unchecked start out...
authorBastien Montagne <montagne29@wanadoo.fr>
Sun, 18 May 2014 20:05:21 +0000 (22:05 +0200)
committerBastien Montagne <montagne29@wanadoo.fr>
Sun, 18 May 2014 20:05:21 +0000 (22:05 +0200)
So! First, frame for absolute shape keys: never allow a new key to have the same pos as an
existing one (this does not make sense). This way, the two workflows are possible (create
all keys and then animate ctime, or animate ctime and then create keys where you need them).

Also, fixed UIList for shapekeys, the "absolute" test was wrong, and better to show frame
value, even though not editable, than nothing in case of absolute keys.

And finally, add getter to RNA 'frame' readonly value, so that we output real frame values,
and not dummy internal ones (which are /100) in our API.

release/scripts/startup/bl_ui/properties_data_mesh.py
source/blender/blenkernel/intern/key.c
source/blender/editors/object/object_shapekey.c
source/blender/makesrna/intern/rna_key.c

index 622c9ba24453a3fe63e0421f5b949fb7bd12add3..41cf93f71ad04e2387ed1011e1b63ddc04367610 100644 (file)
@@ -61,7 +61,7 @@ class MESH_MT_shape_key_specials(Menu):
 
 class MESH_UL_vgroups(UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
-        # assert(isinstance(item, bpy.types.VertexGroup)
+        # assert(isinstance(item, bpy.types.VertexGroup))
         vgroup = item
         if self.layout_type in {'DEFAULT', 'COMPACT'}:
             layout.prop(vgroup, "name", text="", emboss=False, icon_value=icon)
@@ -74,7 +74,7 @@ class MESH_UL_vgroups(UIList):
 
 class MESH_UL_shape_keys(UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
-        # assert(isinstance(item, bpy.types.ShapeKey)
+        # assert(isinstance(item, bpy.types.ShapeKey))
         obj = active_data
         # key = data
         key_block = item
@@ -84,7 +84,9 @@ class MESH_UL_shape_keys(UIList):
             row = split.row(align=True)
             if key_block.mute or (obj.mode == 'EDIT' and not (obj.use_shape_key_edit_mode and obj.type == 'MESH')):
                 row.active = False
-            if not item.relative_key or index > 0:
+            if not item.id_data.use_relative:
+                row.prop(key_block, "frame", text="", emboss=False)
+            elif index > 0:
                 row.prop(key_block, "value", text="", emboss=False)
             else:
                 row.label(text="")
@@ -96,7 +98,7 @@ class MESH_UL_shape_keys(UIList):
 
 class MESH_UL_uvmaps_vcols(UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
-        # assert(isinstance(item, (bpy.types.MeshTexturePolyLayer, bpy.types.MeshLoopColorLayer))
+        # assert(isinstance(item, (bpy.types.MeshTexturePolyLayer, bpy.types.MeshLoopColorLayer)))
         if self.layout_type in {'DEFAULT', 'COMPACT'}:
             layout.prop(item, "name", text="", emboss=False, icon_value=icon)
             icon = 'RESTRICT_RENDER_OFF' if item.active_render else 'RESTRICT_RENDER_ON'
index 0f04c03688c66c75579be4012461b659494cb228..2dc615c19f91b47f8ad1898b5a6b0ef7de8e2ecf 100644 (file)
@@ -1558,9 +1558,23 @@ KeyBlock *BKE_keyblock_add(Key *key, const char *name)
 KeyBlock *BKE_keyblock_add_ctime(Key *key, const char *name, const bool do_force)
 {
        KeyBlock *kb = BKE_keyblock_add(key, name);
+       const float cpos = key->ctime / 100.0f;
 
+       /* In case of absolute keys, there is no point in adding more than one key with the same pos.
+        * Hence only set new keybloc pos to current time if none previous one already use it.
+        * Now at least people just adding absolute keys without touching to ctime
+        * won't have to systematically use retiming func (and have ordering issues, too). See T39897.
+        */
+       if (!do_force && (key->type != KEY_RELATIVE)) {
+               KeyBlock *it_kb;
+               for (it_kb = key->block.first; it_kb; it_kb = it_kb->next) {
+                       if (it_kb->pos == cpos) {
+                               return kb;
+                       }
+               }
+       }
        if (do_force || (key->type != KEY_RELATIVE)) {
-               kb->pos = key->ctime / 100.0f;
+               kb->pos = cpos;
                BKE_key_sort(key);
        }
 
index 5dd20a76e2856b2a2860fdff46140cf20c77a737..cfd1c4d3b0af1d1b4d1d7bf924e9b412b1676b83 100644 (file)
@@ -334,7 +334,7 @@ void OBJECT_OT_shape_key_add(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
-       RNA_def_boolean(ot->srna, "from_mix", 1, "From Mix", "Create the new shape key from the existing mix of keys");
+       RNA_def_boolean(ot->srna, "from_mix", true, "From Mix", "Create the new shape key from the existing mix of keys");
 }
 
 static int shape_key_remove_exec(bContext *C, wmOperator *op)
index a72e207178bacbb8b75a1f3a7349271f78457da5..7d10511d1c42866c5f1522494f719ff9ad08315f 100644 (file)
@@ -92,6 +92,12 @@ static void rna_ShapeKey_name_set(PointerRNA *ptr, const char *value)
        BKE_all_animdata_fix_paths_rename(NULL, "key_blocks", oldname, kb->name);
 }
 
+static float rna_ShapeKey_frame_get(PointerRNA *ptr)
+{
+       KeyBlock *kb = (KeyBlock *)ptr->data;
+       return kb->pos * 100.0f;  /* Because pos is ctime/100... */
+}
+
 static void rna_ShapeKey_value_set(PointerRNA *ptr, float value)
 {
        KeyBlock *data = (KeyBlock *)ptr->data;
@@ -571,6 +577,7 @@ static void rna_def_keyblock(BlenderRNA *brna)
        prop = RNA_def_property(srna, "frame", PROP_FLOAT, PROP_TIME);
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
        RNA_def_property_float_sdna(prop, NULL, "pos");
+       RNA_def_property_float_funcs(prop, "rna_ShapeKey_frame_get", NULL, NULL);
        RNA_def_property_ui_text(prop, "Frame", "Frame for absolute keys");
        RNA_def_property_update(prop, 0, "rna_Key_update_data");