-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathoperator_create_stretch_bone.py
112 lines (75 loc) · 3.27 KB
/
operator_create_stretch_bone.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import bpy
from mathutils import Vector
from bpy.props import IntProperty
def print_current_bones(armature):
bpy.context.scene.update()
print("Current edit bones")
for b in armature.data.bones:
print(b.name)
print("Current pose bones")
for b in armature.pose.bones:
print(b.name)
def subdivide_bone(armature, bone, divisions):
div = 1/(divisions+1)
new_bones = []
for i in range(0,divisions+1):
new_bone = armature.data.edit_bones.new(bone.name + "__" + str(i))
new_bone.head.xyz = bone.head.xyz + ((bone.tail.xyz - bone.head.xyz) * div * i)
new_bone.tail.xyz = bone.head.xyz + ((bone.tail.xyz - bone.head.xyz) * div * (i+1))
new_bones.append(new_bone)
return new_bones
def make_stretchy_bone(bone, divisions):
bone.use_deform = False
armature = bpy.context.selected_objects[0]
target_bone = armature.data.edit_bones.new(bone.name + '_head')
target_bone.head.xyz = bone.head.xyz
target_bone.tail.xyz = bone.head.xyz + (0.1 * bone.z_axis)
bone.parent = target_bone
target_bone.use_deform = False
new_bones = subdivide_bone(armature, bone, divisions)
next_parent = bone
for i, child_bone in enumerate(new_bones):
child_bone.use_connect = False
child_bone.parent = next_parent
child_bone.use_deform = True
armature.update_from_editmode()
target_bone = armature.data.edit_bones.new(child_bone.name + '_target')
target_bone.head.xyz = child_bone.tail.xyz
target_bone.tail.xyz = child_bone.tail.xyz + (0.1 * bone.z_axis)
target_bone.parent = bone
target_bone.use_deform = False
next_parent = target_bone
armature.update_from_editmode()
pose_bone = armature.pose.bones[child_bone.name]
stretch_constraint = pose_bone.constraints.new(type="STRETCH_TO")
stretch_constraint.target = armature
stretch_constraint.subtarget = target_bone.name
target_bone.parent = None
armature.update_from_editmode()
pose_bone = armature.pose.bones[bone.name]
stretch_constraint = pose_bone.constraints.new(type="STRETCH_TO")
stretch_constraint.target = armature
stretch_constraint.subtarget = target_bone.name
class MakeStretchyBoneOperator(bpy.types.Operator):
"""Converts a bone to a stretchy bone"""
bl_idname = "bone.make_stretchy_bone"
bl_label = "Make stretchy bone"
bl_options = {'REGISTER', 'UNDO'}
divisions = bpy.props.IntProperty(name='Divisions', default=2)
@classmethod
def poll(cls, context):
return context.active_object.type == 'ARMATURE' and \
context.object.mode == 'EDIT' and \
context.selected_editable_bones != None
def invoke(self, context, event):
return self.execute(context)
def execute(self, context: bpy.types.Context):
for bone in context.selected_editable_bones:
make_stretchy_bone(bone, self.divisions)
return {'FINISHED'}
def register():
bpy.utils.register_class(MakeStretchyBoneOperator)
def unregister():
bpy.utils.unregister_class(MakeStretchyBoneOperator)
if __name__ == "__main__":
register()