From 7158e02aed0eb1acee8ea8a7a68986613b55a3f6 Mon Sep 17 00:00:00 2001 From: Nika Kutsniashvili Date: Fri, 1 Aug 2025 15:43:31 +0200 Subject: [PATCH] Modeling: Set shape key default value to 1.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When adding a shape key, set its blend value to 1.0 / 100%. There is no practical use case where user wants to add shape key but not work on it. New shape keys at value 0 have no purpose. Adding shape key should be interpreted by Blender as user wanting to sculpt/model on it. Also, being at 1.0 initially doesn't change anything visually, because key isn't edited yet and it doesn't deform mesh. The default value of the shape key is also set to 1.0. When using right-click to reset values, user most often wants to return to 1 (which is "correct" state of deformation without multiplication) rather than 0 (which is no deformation at all). Co-authored-by: Sybren A. Stüvel Pull Request: https://projects.blender.org/blender/blender/pulls/133399 --- scripts/addons_core/io_scene_fbx/import_fbx.py | 1 + scripts/addons_core/io_scene_gltf2/blender/imp/mesh.py | 4 ++-- scripts/startup/bl_operators/object.py | 1 + source/blender/editors/object/object_shapekey.cc | 3 +++ source/blender/makesrna/intern/rna_key.cc | 1 + source/blender/makesrna/intern/rna_object_api.cc | 4 ++++ tests/python/bl_animation_drivers.py | 1 + tests/utils/bl_run_operators.py | 5 +++-- tools/utils_maintenance/blender_menu_search_coverage.py | 5 +++-- 9 files changed, 19 insertions(+), 6 deletions(-) diff --git a/scripts/addons_core/io_scene_fbx/import_fbx.py b/scripts/addons_core/io_scene_fbx/import_fbx.py index 7d1620bac28..9f3503c10f4 100644 --- a/scripts/addons_core/io_scene_fbx/import_fbx.py +++ b/scripts/addons_core/io_scene_fbx/import_fbx.py @@ -2009,6 +2009,7 @@ def blen_read_shapes(fbx_tmpl, fbx_data, objects, me, scene): if me.shape_keys is None: objects[0].shape_key_add(name="Basis", from_mix=False) kb = objects[0].shape_key_add(name=elem_name_utf8, from_mix=False) + kb.value = 0.0 me.shape_keys.use_relative = True # Should already be set as such. # Only need to set the shape key co if there are any non-zero dvcos. diff --git a/scripts/addons_core/io_scene_gltf2/blender/imp/mesh.py b/scripts/addons_core/io_scene_gltf2/blender/imp/mesh.py index 8e45be2f876..7733b858b89 100644 --- a/scripts/addons_core/io_scene_gltf2/blender/imp/mesh.py +++ b/scripts/addons_core/io_scene_gltf2/blender/imp/mesh.py @@ -388,8 +388,8 @@ def do_primitives(gltf, mesh_idx, skin_idx, mesh, ob): if sk_name is None: continue - ob.shape_key_add(name=sk_name) - key_block = mesh.shape_keys.key_blocks[sk_name] + key_block = ob.shape_key_add(name=sk_name) + key_block.value = 0.0 key_block.points.foreach_set('co', squish(sk_vert_locs[sk_i], np.float32)) sk_i += 1 diff --git a/scripts/startup/bl_operators/object.py b/scripts/startup/bl_operators/object.py index a0a6afdbd06..7c5d1846652 100644 --- a/scripts/startup/bl_operators/object.py +++ b/scripts/startup/bl_operators/object.py @@ -372,6 +372,7 @@ class ShapeTransfer(Operator): if len(me.shape_keys.key_blocks) == 1: key.name = "Basis" key = ob.shape_key_add(from_mix=False) # we need a rest + key.value = 0.0 key.name = name ob.active_shape_key_index = len(me.shape_keys.key_blocks) - 1 ob.show_only_shape_key = True diff --git a/source/blender/editors/object/object_shapekey.cc b/source/blender/editors/object/object_shapekey.cc index e1f5aaf41a6..79bc14cf8af 100644 --- a/source/blender/editors/object/object_shapekey.cc +++ b/source/blender/editors/object/object_shapekey.cc @@ -143,6 +143,9 @@ static void object_shape_key_add(bContext *C, Object *ob, const bool from_mix) Main *bmain = CTX_data_main(C); KeyBlock *kb = BKE_object_shapekey_insert(bmain, ob, nullptr, from_mix); if (kb) { + /* Shapekeys created via this operator should get default value 1.0. */ + kb->curval = 1.0f; + Key *key = BKE_key_from_object(ob); /* for absolute shape keys, new keys may not be added last */ ob->shapenr = BLI_findindex(&key->block, kb) + 1; diff --git a/source/blender/makesrna/intern/rna_key.cc b/source/blender/makesrna/intern/rna_key.cc index 4dc884835cb..ba9b61dce7d 100644 --- a/source/blender/makesrna/intern/rna_key.cc +++ b/source/blender/makesrna/intern/rna_key.cc @@ -964,6 +964,7 @@ static void rna_def_keyblock(BlenderRNA *brna) prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, nullptr, "curval"); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_float_funcs( prop, nullptr, "rna_ShapeKey_value_set", "rna_ShapeKey_value_range"); RNA_def_property_ui_range(prop, -10.0f, 10.0f, 10, 3); diff --git a/source/blender/makesrna/intern/rna_object_api.cc b/source/blender/makesrna/intern/rna_object_api.cc index 3347c18e73e..f94870e4830 100644 --- a/source/blender/makesrna/intern/rna_object_api.cc +++ b/source/blender/makesrna/intern/rna_object_api.cc @@ -458,6 +458,10 @@ static PointerRNA rna_Object_shape_key_add( KeyBlock *kb = nullptr; if ((kb = BKE_object_shapekey_insert(bmain, ob, name, from_mix))) { + /* Set the initial blend value. */ + kb->curval = 1.0f; + CLAMP(kb->curval, kb->slidermin, kb->slidermax); + PointerRNA keyptr = RNA_pointer_create_discrete( (ID *)BKE_key_from_object(ob), &RNA_ShapeKey, kb); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); diff --git a/tests/python/bl_animation_drivers.py b/tests/python/bl_animation_drivers.py index 6c81a60aa03..6f0dfb30886 100644 --- a/tests/python/bl_animation_drivers.py +++ b/tests/python/bl_animation_drivers.py @@ -249,6 +249,7 @@ class SubDataDriverRemovalTest(AbstractEmptyDriverTest, unittest.TestCase): def test_remove_shapekey(self): self.obj.shape_key_add(name="base") test_key = self.obj.shape_key_add(name="test") + test_key.value = 0.0 # Due to the weirdness of shapekeys, this is an ID. shape_key_id = self.obj.data.shape_keys self.assertEqual(len(shape_key_id.key_blocks), 2) diff --git a/tests/utils/bl_run_operators.py b/tests/utils/bl_run_operators.py index 39fef8e6811..ab7e97ab276 100644 --- a/tests/utils/bl_run_operators.py +++ b/tests/utils/bl_run_operators.py @@ -126,8 +126,9 @@ def ctx_editmode_mesh(): def ctx_editmode_mesh_extra(): bpy.ops.wm.read_factory_settings(use_empty=False) bpy.ops.object.vertex_group_add() - bpy.ops.object.shape_key_add(from_mix=False) - bpy.ops.object.shape_key_add(from_mix=True) + bpy.ops.object.shape_key_add(from_mix=False) # Basis Key + shape_key = bpy.ops.object.shape_key_add(from_mix=True) + shape_key.value = 0.0 bpy.ops.mesh.uv_texture_add() bpy.ops.object.material_slot_add() # editmode last! diff --git a/tools/utils_maintenance/blender_menu_search_coverage.py b/tools/utils_maintenance/blender_menu_search_coverage.py index ef0a3efc6ba..77dcd6782e1 100644 --- a/tools/utils_maintenance/blender_menu_search_coverage.py +++ b/tools/utils_maintenance/blender_menu_search_coverage.py @@ -422,8 +422,9 @@ def ctx_editmode_mesh(): def ctx_editmode_mesh_extra(): bpy.ops.object.vertex_group_add() - bpy.ops.object.shape_key_add(from_mix=False) - bpy.ops.object.shape_key_add(from_mix=True) + bpy.ops.object.shape_key_add(from_mix=False) # Basis Key + shape_key = bpy.ops.object.shape_key_add(from_mix=True) + shape_key.value = 0.0 bpy.ops.mesh.uv_texture_add() bpy.ops.mesh.vertex_color_add() bpy.ops.object.material_slot_add()