Skip to content

Commit b33d63e

Browse files
committed
feat: update to 1.3.1
- new feature: Select all affected vertices
1 parent 64b5722 commit b33d63e

File tree

5 files changed

+172
-92
lines changed

5 files changed

+172
-92
lines changed

README.md

Lines changed: 83 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,83 @@
1-
## [**`👉 Download Latest Version 👈`**](https://github.com/namakoshiro/blender-shapekey-tools/releases/download/v1.3.0/blender-shapekey-tools-v1.3.0.zip)
2-
3-
- **For first time installation**
4-
- Drag the `Zip` file into Blender and click `OK`
5-
- Search for `Shapekey Tools` in `Preferences` > `Add-ons`
6-
- Make sure `Shapekey Tools` is enabled
7-
- Press shortcut key `N` in viewport to open the `N-Panel`
8-
9-
- **For update from previous version to 1.3.0 and later**
10-
- Drag the `Zip` file into Blender and click `OK`
11-
- `Restart` Blender to complete the update
12-
13-
- **For update from version 1.3.0**
14-
- Press `Update` button to update the addon online
15-
- In case it's not working, please manually [`Download Latest Version`](https://github.com/namakoshiro/blender-shapekey-tools/releases/download/v1.3.0/blender-shapekey-tools-v1.3.0.zip)
16-
- Press `Install` button and select `Zip` file to update the addon
17-
18-
## **😊 Information**
19-
20-
**This is a Blender add-on for one-click to split or merge L/R shapekeys, and create new shapekey below the selected**
21-
22-
- Author: [`namakoshiro`](https://x.com/namakoshiro)
23-
- Version: `1.3.0`
24-
- Last Updated: `2025/3/14`
25-
26-
## **📖 How to Use**
27-
28-
- **New Empty Shapekey**
29-
- Add a new empty shapekey below the selected
30-
31-
- **New Shapekey from Mix**
32-
- Capture the current mix as a new shapekey below the selected
33-
34-
- **Delete All Except Locked**
35-
- Delete all shapekeys except basis and locked ones
36-
37-
- **Mirror Shapekey**
38-
- Generate a mirrored version of the selected shapekey below the selected
39-
40-
- **Split Shapekey L/R**
41-
- Split a shapekey into L/R versions below the selected
42-
43-
- **Smoothly Split Mouth L/R**
44-
- Smoothly split mouth shapekey into L/R with weighted transition
45-
- Animations of teeth and tongue will be scaled down but won't be tilted like lips
46-
47-
## **Update History**
48-
49-
- **v1.3.0 (2025/3/14)**
50-
- Convert to multi-file system
51-
- New feature: Update from online/local
52-
53-
- **v1.2.2 (2025/1/16)**
54-
- Change info name to "Shapekey Tools"
55-
- Change info category to "Rigging"
56-
57-
- **v1.2.1 (2025/1/16)**
58-
- Feature: Delete All Except Locked only available on Blender ≥ 4.2
59-
- Enhance functions
60-
61-
- **v1.2.0 (2025/1/15)**
62-
- New Feature: Delete All Except Locked
63-
- New Feature: Smoothly Split Mouth L/R
64-
- Enhance functions
65-
- Fix problems
66-
67-
- **v1.1.2 (2025/1/14)**
68-
- New Feature: Smoothly Split Mouth L/R (Experimental)
69-
- Fix problems
70-
71-
- **v1.1.0 (2025/1/13)**
72-
- Add support for Blender version from 2.80 to 4.3
73-
- Enhance UI
74-
- Enhance functions
75-
76-
- **v1.0.0 (2025/1/12)**
77-
- Public release
1+
## [**`👉 Download Latest Version 👈`**](https://github.com/namakoshiro/blender-shapekey-tools/releases/download/v1.3.1/blender-shapekey-tools-v1.3.1.zip)
2+
3+
- **For first time installation**
4+
- Drag the `Zip` file into Blender and click `OK`
5+
- Search for `Shapekey Tools` in `Preferences` > `Add-ons`
6+
- Make sure `Shapekey Tools` is enabled
7+
- Press shortcut key `N` in viewport to open the `N-Panel`
8+
9+
- **For update from previous version to 1.3.0 and later**
10+
- Drag the `Zip` file into Blender and click `OK`
11+
- `Restart` Blender to complete the update
12+
13+
- **For update from version 1.3.0**
14+
- Press `Update` button to update the addon online
15+
- In case it's not working, please manually [`Download Latest Version`](https://github.com/namakoshiro/blender-shapekey-tools/releases/download/v1.3.1/blender-shapekey-tools-v1.3.1.zip)
16+
- Press `Install` button and select `Zip` file to update the addon
17+
18+
## **😊 Information**
19+
20+
**This is a Blender add-on for one-click to split or merge L/R shapekeys, and create new shapekey below the selected**
21+
22+
- Author: [`namakoshiro`](https://x.com/namakoshiro)
23+
- Version: `1.3.1`
24+
- Last Updated: `2025/3/17`
25+
26+
## **📖 How to Use**
27+
28+
- **New Empty Shapekey**
29+
- Add a new empty shapekey below the selected
30+
31+
- **New Shapekey from Mix**
32+
- Capture the current mix as a new shapekey below the selected
33+
34+
- **Delete All Except Locked**
35+
- Delete all shapekeys except basis and locked ones
36+
37+
- **Mirror Shapekey**
38+
- Generate a mirrored version of the selected shapekey below the selected
39+
40+
- **Split Shapekey L/R**
41+
- Split a shapekey into L/R versions below the selected
42+
43+
- **Smoothly Split Mouth L/R**
44+
- Smoothly split mouth shapekey into L/R with weighted transition
45+
- Animations of teeth and tongue will be scaled down but won't be tilted like lips
46+
47+
- **Select All Affected Vertices**
48+
- Select all vertices affected of the selected shapekey in Edit Mode
49+
50+
## **Update History**
51+
52+
- **1.3.1 (2025/3/17)**
53+
- New feature: Select All Affected Vertices
54+
55+
- **1.3.0 (2025/3/14)**
56+
- Convert to multi-file system
57+
- New feature: Update from online/local
58+
59+
- **1.2.2 (2025/1/16)**
60+
- Change info name to "Shapekey Tools"
61+
- Change info category to "Rigging"
62+
63+
- **1.2.1 (2025/1/16)**
64+
- Feature: Delete All Except Locked only available on Blender ≥ 4.2
65+
- Enhance functions
66+
67+
- **1.2.0 (2025/1/15)**
68+
- New Feature: Delete All Except Locked
69+
- New Feature: Smoothly Split Mouth L/R
70+
- Enhance functions
71+
- Fix problems
72+
73+
- **1.1.2 (2025/1/14)**
74+
- New Feature: Smoothly Split Mouth L/R (Experimental)
75+
- Fix problems
76+
77+
- **1.1.0 (2025/1/13)**
78+
- Add support for Blender version from 2.80 to 4.3
79+
- Enhance UI
80+
- Enhance functions
81+
82+
- **1.0.0 (2025/1/12)**
83+
- Public release

__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
bl_info = {
22
"name": "Shapekey Tools",
33
"author": "namakoshiro",
4-
"version": (1, 3, 0),
4+
"version": (1, 3, 1),
55
"blender": (2, 80, 0),
66
"location": "View3D > Sidebar > Shapekey",
77
"description": "This is a Blender addon to manage shapekeys",
@@ -25,6 +25,7 @@
2525
from .modules import add_shapekey_below
2626
from .modules import add_shapekey_from_mix
2727
from .modules import delete_unlocked_shapekeys
28+
from .modules import select_affected_vertices
2829
from .modules import shapekey_mirror
2930
from .modules import shapekey_split_lr
3031
from .modules import smooth_split_mouth_lr
@@ -34,6 +35,7 @@ def register():
3435
add_shapekey_below.register()
3536
add_shapekey_from_mix.register()
3637
delete_unlocked_shapekeys.register()
38+
select_affected_vertices.register()
3739
shapekey_mirror.register()
3840
shapekey_split_lr.register()
3941
smooth_split_mouth_lr.register()
@@ -51,6 +53,7 @@ def unregister():
5153
smooth_split_mouth_lr.unregister()
5254
shapekey_split_lr.unregister()
5355
shapekey_mirror.unregister()
56+
select_affected_vertices.unregister()
5457
delete_unlocked_shapekeys.unregister()
5558
add_shapekey_from_mix.unregister()
5659
add_shapekey_below.unregister()
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import bpy
2+
from bpy.types import Operator
3+
import bmesh
4+
from mathutils import Vector
5+
6+
class SELECT_OT_affected_vertices(Operator):
7+
bl_idname = "object.select_affected_vertices"
8+
bl_label = "Select All Affected Vertices"
9+
bl_description = "Select all affected vertices of the selected shapekey in Edit Mode"
10+
bl_options = {'REGISTER', 'UNDO'}
11+
12+
@classmethod
13+
def poll(cls, context):
14+
# Check if object is mesh with shapekeys and in edit mode
15+
obj = context.active_object
16+
return (obj and obj.type == 'MESH' and obj.data.shape_keys
17+
and context.mode == 'EDIT_MESH' and obj.active_shape_key_index > 0)
18+
19+
def execute(self, context):
20+
try:
21+
obj = context.active_object
22+
shape_keys = obj.data.shape_keys
23+
if not shape_keys:
24+
return {'CANCELLED'}
25+
26+
# Get the selected shapekey
27+
active_key_index = obj.active_shape_key_index
28+
if active_key_index <= 0: # Skip basis
29+
self.report({'WARNING'}, "Please select a shapekey")
30+
return {'CANCELLED'}
31+
32+
active_key = shape_keys.key_blocks[active_key_index]
33+
basis_key = shape_keys.key_blocks[0]
34+
35+
# Get mesh data
36+
bm = bmesh.from_edit_mesh(obj.data)
37+
38+
# Deselect all vertices first
39+
for v in bm.verts:
40+
v.select = False
41+
42+
# Threshold for considering a vertex affected (can be adjusted)
43+
threshold = 0.0001
44+
45+
# Count affected vertices
46+
affected_count = 0
47+
48+
# Compare active shapekey with basis and select affected vertices
49+
for i, (basis_co, active_co) in enumerate(zip(basis_key.data, active_key.data)):
50+
# Calculate difference vector
51+
diff = Vector(active_co.co) - Vector(basis_co.co)
52+
53+
# If the difference is significant, select the vertex
54+
if diff.length > threshold:
55+
bm.verts[i].select = True
56+
affected_count += 1
57+
58+
# Update the mesh
59+
bmesh.update_edit_mesh(obj.data)
60+
61+
# Report results
62+
self.report({'INFO'}, f"Selected {affected_count} affected vertices")
63+
64+
return {'FINISHED'}
65+
66+
except Exception as e:
67+
self.report({'ERROR'}, f"Failed to select vertices: {str(e)}")
68+
return {'CANCELLED'}
69+
70+
# Register
71+
def register():
72+
bpy.utils.register_class(SELECT_OT_affected_vertices)
73+
74+
# Unregister
75+
def unregister():
76+
bpy.utils.unregister_class(SELECT_OT_affected_vertices)

modules/smooth_split_mouth_lr.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ def find_face_mesh(self, obj):
9595
return set(island_data[0]['verts'])
9696

9797
def calculate_custom_weight(self, position, is_upward):
98-
"""Calculate transition weight for vertex position"""
9998
if is_upward:
10099
# Keep full weight in first 30% for upper lip
101100
if position <= 0.3:

ui/panels.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,16 @@ def poll(cls, context):
1212
# Check if object is mesh with shapekeys
1313
obj = context.active_object
1414
return obj and obj.type == 'MESH' and obj.data.shape_keys
15-
15+
1616
def draw(self, context):
1717
layout = self.layout
1818
obj = context.active_object
1919

2020
# Check conditions
2121
is_object_mode = context.mode == 'OBJECT'
22+
is_edit_mode = context.mode == 'EDIT_MESH'
2223
has_active_non_basis = obj.active_shape_key_index > 0
2324

24-
# Show warning if not in object mode
25-
if not is_object_mode:
26-
box = layout.box()
27-
box.alert = True
28-
box.label(text="Work in Object Mode", icon='ERROR')
29-
layout.separator()
30-
31-
# Basic operators section
3225
box = layout.box()
3326
col = box.column(align=True)
3427
col.enabled = is_object_mode
@@ -39,15 +32,18 @@ def draw(self, context):
3932
if bpy.app.version >= (4, 2, 0):
4033
col.operator("object.delete_unlocked_shapekeys", icon='REMOVE')
4134

42-
# Mirror and split operators section
4335
box = layout.box()
4436
col = box.column(align=True)
4537
col.enabled = is_object_mode and has_active_non_basis
4638
col.operator("object.add_shapekey_mirror", icon='ARROW_LEFTRIGHT')
4739
col.operator("object.add_shapekey_split_lr", icon='MOD_MIRROR')
4840
col.operator("object.add_shapekey_smooth_split_mouth_lr", icon='MOD_MIRROR')
4941

50-
# Version and update section
42+
box = layout.box()
43+
col = box.column(align=True)
44+
col.enabled = is_edit_mode and has_active_non_basis
45+
col.operator("object.select_affected_vertices", icon='VERTEXSEL')
46+
5147
layout.separator()
5248
box = layout.box()
5349
row = box.row(align=True)
@@ -65,8 +61,8 @@ def draw(self, context):
6561

6662
# Version Info
6763
col = box.column()
68-
col.label(text="Version: 1.3.0")
69-
col.label(text="Last Updated: 2025/3/14")
64+
col.label(text="Version: 1.3.1")
65+
col.label(text="Last Updated: 2025/3/17")
7066
if hasattr(bpy.types.Scene, "shapekey_tools_update_available"):
7167
if hasattr(bpy.context.scene, "shapekey_tools_update_check_in_progress") and bpy.context.scene.shapekey_tools_update_check_in_progress:
7268
col.label(text="Checking update...")

0 commit comments

Comments
 (0)