-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path__init__.py
133 lines (102 loc) · 3.33 KB
/
__init__.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import bpy
bl_info = {
"name": "Bone Traversal",
"blender": (2, 93, 0),
"category": "3D View",
}
def select_bones(bones, select=True):
"""Select a list of bones"""
for bone in bones:
bone.select = select
def set_armature_active_bone(bone):
"""Update the Armatures active bone to refresh properties panel"""
arm = bpy.context.active_object
arm.data.bones.active = bone
def set_bones():
"""Set a list of bones for bone traversal"""
pose_bones = bpy.context.selected_pose_bones_from_active_object
bones = [pose_bone.bone for pose_bone in pose_bones]
select_bones(bones)
bpy.props.cur_bones = bones
bpy.props.cur_bone = None
def next_bone():
"""Select the next bone in the list of bones"""
cur_bones = bpy.props.cur_bones
if cur_bones is None:
raise Exception('run bones.set first')
cur_bones_len = len(cur_bones)
cur_bone = getattr(bpy.props, 'cur_bone', None)
if cur_bone is None:
index = -1
else:
index = cur_bones.index(cur_bone)
next_index = 0 if index + 1 == cur_bones_len else index + 1
next_bone = cur_bones[next_index]
select_bones(cur_bones, False)
select_bones([next_bone])
set_armature_active_bone(next_bone)
bpy.props.cur_bone = next_bone
def prev_bone():
"""Select the previous bone in the list of bones"""
cur_bones = bpy.props.cur_bones
if cur_bones is None:
raise Exception('run bones.set first')
cur_bones_len = len(cur_bones)
cur_bone = getattr(bpy.props, 'cur_bone', None)
if cur_bone is None:
index = cur_bones_len - 1
else:
index = cur_bones.index(cur_bone)
prev_index = cur_bones_len - 1 if index - 1 == -1 else index - 1
prev_bone = cur_bones[prev_index]
select_bones(cur_bones, False)
select_bones([prev_bone])
set_armature_active_bone(prev_bone)
bpy.props.cur_bone = prev_bone
class Panel(bpy.types.Panel):
"""Show Bone Traversal side panel in 3D View"""
bl_idname = "BONE_TRAVERSAL_PT_PANEL"
bl_label = "Bone Traversal"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = "Bone Traversal"
@classmethod
def poll(cls, context):
return context.mode in {'POSE'}
def draw(self, context):
layout = self.layout
box = layout.box()
box.operator("bones.set")
row = box.row()
row.operator("bones.prev")
row.operator("bones.next")
class OpSetBones(bpy.types.Operator):
bl_idname = 'bones.set'
bl_label = 'Set Bones'
def execute(self, context):
set_bones()
return {'FINISHED'}
class OpNextBone(bpy.types.Operator):
bl_idname = 'bones.next'
bl_label = 'Next Bone'
def execute(self, context):
next_bone()
return {'FINISHED'}
class OpPrevBone(bpy.types.Operator):
bl_idname = 'bones.prev'
bl_label = 'Prev Bone'
def execute(self, context):
prev_bone()
return {'FINISHED'}
def register():
bpy.utils.register_class(OpSetBones)
bpy.utils.register_class(OpNextBone)
bpy.utils.register_class(OpPrevBone)
bpy.utils.register_class(Panel)
def unregister():
bpy.utils.unregister_class(OpSetBones)
bpy.utils.unregister_class(OpNextBone)
bpy.utils.unregister_class(OpPrevBone)
bpy.utils.unregister_class(Panel)
if __name__ == "__main__":
register()