Bone constraints are now in a separate tab. It's more consistent
[blender.git] / release / ui / buttons_data_bone.py
1
2 import bpy
3  
4 class BoneButtonsPanel(bpy.types.Panel):
5         __space_type__ = 'PROPERTIES'
6         __region_type__ = 'WINDOW'
7         __context__ = "bone"
8         
9         def poll(self, context):
10                 return (context.bone or context.edit_bone)
11
12 class BONE_PT_context_bone(BoneButtonsPanel):
13         __show_header__ = False
14
15         def draw(self, context):
16                 layout = self.layout
17                 
18                 bone = context.bone
19                 if not bone:
20                         bone = context.edit_bone
21                 
22                 row = layout.row()
23                 row.itemL(text="", icon='ICON_BONE_DATA')
24                 row.itemR(bone, "name", text="")
25
26 class BONE_PT_transform(BoneButtonsPanel):
27         __label__ = "Transform"
28
29         def draw(self, context):
30                 layout = self.layout
31                 
32                 ob = context.object
33                 bone = context.bone
34                 if not bone:
35                         bone = context.edit_bone
36
37                         row = layout.row()
38                         row.column().itemR(bone, "head")
39                         row.column().itemR(bone, "tail")
40
41                         col = row.column()
42                         sub = col.column(align=True)
43                         sub.itemL(text="Roll:")
44                         sub.itemR(bone, "roll", text="")
45                         sub.itemL()
46                         sub.itemR(bone, "locked")
47
48                 else:
49                         pchan = ob.pose.pose_channels[context.bone.name]
50
51                         layout.itemR(pchan, "rotation_mode")
52
53                         row = layout.row()
54                         col = row.column()
55                         col.itemR(pchan, "location")
56                         col.active = not (bone.parent and bone.connected)
57
58                         col = row.column()
59                         if pchan.rotation_mode == 'QUATERNION':
60                                 col.itemR(pchan, "rotation", text="Rotation")
61                         elif pchan.rotation_mode == 'AXIS_ANGLE':
62                                 col.itemL(text="Rotation")
63                                 col.itemR(pchan, "rotation_angle", text="Angle")
64                                 col.itemR(pchan, "rotation_axis", text="Axis")
65                         else:
66                                 col.itemR(pchan, "euler_rotation", text="Rotation")
67
68                         row.column().itemR(pchan, "scale")
69
70                         if pchan.rotation_mode == 'QUATERNION':
71                                 col = layout.column(align=True)
72                                 col.itemL(text="Euler:")
73                                 col.row().itemR(pchan, "euler_rotation", text="")
74                                 
75 class BONE_PT_transform_locks(BoneButtonsPanel):
76         __label__ = "Transform Locks"
77         __default_closed__ = True
78         
79         def poll(self, context):
80                 return context.bone
81         
82         def draw(self, context):
83                 layout = self.layout
84                 
85                 ob = context.object
86                 bone = context.bone
87                 pchan = ob.pose.pose_channels[context.bone.name]
88                 
89                 row = layout.row()
90                 col = row.column()
91                 col.itemR(pchan, "lock_location")
92                 col.active = not (bone.parent and bone.connected)
93                 
94                 col = row.column()
95                 if pchan.rotation_mode in ('QUATERNION', 'AXIS_ANGLE'):
96                         col.itemR(pchan, "lock_rotations_4d", text="Lock Rotation")
97                         if pchan.lock_rotations_4d:
98                                 col.itemR(pchan, "lock_rotation_w", text="W")
99                         col.itemR(pchan, "lock_rotation", text="")
100                 else:
101                         col.itemR(pchan, "lock_rotation", text="Rotation")
102                 
103                 row.column().itemR(pchan, "lock_scale")
104
105 class BONE_PT_bone(BoneButtonsPanel):
106         __label__ = "Bone"
107
108         def draw(self, context):
109                 layout = self.layout
110                 
111                 ob = context.object
112                 bone = context.bone
113                 arm = context.armature
114                 
115                 if not bone:
116                         bone = context.edit_bone
117                         pchan = None
118                 else:
119                         pchan = ob.pose.pose_channels[context.bone.name]
120
121                 split = layout.split()
122
123                 col = split.column()
124                 col.itemL(text="Parent:")
125                 if context.bone:
126                         col.itemR(bone, "parent", text="")
127                 else:
128                         col.item_pointerR(bone, "parent", arm, "edit_bones", text="")
129                 
130                 row = col.row()
131                 row.active = bone.parent != None
132                 row.itemR(bone, "connected")
133                 
134                 col.itemL(text="Layers:")
135                 col.itemR(bone, "layer", text="")
136                 
137                 col = split.column()
138                 col.itemL(text="Inherit:")
139                 col.itemR(bone, "hinge", text="Rotation")
140                 col.itemR(bone, "inherit_scale", text="Scale")
141                 col.itemL(text="Display:")
142                 col.itemR(bone, "draw_wire", text="Wireframe")
143                 col.itemR(bone, "hidden", text="Hide")
144                 
145                 if ob and pchan:
146                         split = layout.split()
147                         
148                         col = split.column()
149                         col.itemL(text="Bone Group:")
150                         col.item_pointerR(pchan, "bone_group", ob.pose, "bone_groups", text="")
151                         
152                         col = split.column()
153                         col.itemL(text="Custom Shape:")
154                         col.itemR(pchan, "custom_shape", text="")
155
156 class BONE_PT_inverse_kinematics(BoneButtonsPanel):
157         __label__ = "Inverse Kinematics"
158         __default_closed__ = True
159         
160         def poll(self, context):
161                 ob = context.object
162                 bone = context.bone
163
164                 if ob and context.bone:
165                         pchan = ob.pose.pose_channels[context.bone.name]
166                         return pchan.has_ik
167                 
168                 return False
169
170         def draw(self, context):
171                 layout = self.layout
172                 
173                 ob = context.object
174                 bone = context.bone
175                 pchan = ob.pose.pose_channels[context.bone.name]
176
177                 split = layout.split(percentage=0.25)
178                 split.itemR(pchan, "ik_dof_x", text="X")
179                 row = split.row()
180                 row.itemR(pchan, "ik_stiffness_x", text="Stiffness")
181                 row.active = pchan.ik_dof_x
182
183                 split = layout.split(percentage=0.25)
184                 row = split.row()
185                 row.itemR(pchan, "ik_limit_x", text="Limit")
186                 row.active = pchan.ik_dof_x
187                 row = split.row(align=True)
188                 row.itemR(pchan, "ik_min_x", text="")
189                 row.itemR(pchan, "ik_max_x", text="")
190                 row.active = pchan.ik_dof_x and pchan.ik_limit_x
191
192                 split = layout.split(percentage=0.25)
193                 split.itemR(pchan, "ik_dof_y", text="Y")
194                 row = split.row()
195                 row.itemR(pchan, "ik_stiffness_y", text="Stiffness")
196                 row.active = pchan.ik_dof_y
197
198                 split = layout.split(percentage=0.25)
199                 row = split.row()
200                 row.itemR(pchan, "ik_limit_y", text="Limit")
201                 row.active = pchan.ik_dof_y
202                 row = split.row(align=True)
203                 row.itemR(pchan, "ik_min_y", text="")
204                 row.itemR(pchan, "ik_max_y", text="")
205                 row.active = pchan.ik_dof_y and pchan.ik_limit_y
206
207                 split = layout.split(percentage=0.25)
208                 split.itemR(pchan, "ik_dof_z", text="Z")
209                 row = split.row()
210                 row.itemR(pchan, "ik_stiffness_z", text="Stiffness")
211                 row.active = pchan.ik_dof_z
212
213                 split = layout.split(percentage=0.25)
214                 row = split.row()
215                 row.itemR(pchan, "ik_limit_z", text="Limit")
216                 row.active = pchan.ik_dof_z
217                 row = split.row(align=True)
218                 row.itemR(pchan, "ik_min_z", text="")
219                 row.itemR(pchan, "ik_max_z", text="")
220                 row.active = pchan.ik_dof_z and pchan.ik_limit_z
221
222                 split = layout.split()
223                 split.itemR(pchan, "ik_stretch", text="Stretch")
224                 split.itemL()
225
226 class BONE_PT_deform(BoneButtonsPanel):
227         __label__ = "Deform"
228         __default_closed__ = True
229
230         def draw_header(self, context):
231                 bone = context.bone
232                 
233                 if not bone:
234                         bone = context.edit_bone
235                         
236                 self.layout.itemR(bone, "deform", text="")
237
238         def draw(self, context):
239                 layout = self.layout
240                 
241                 bone = context.bone
242                 
243                 if not bone:
244                         bone = context.edit_bone
245         
246                 layout.active = bone.deform
247                         
248                 split = layout.split()
249
250                 col = split.column()
251                 col.itemL(text="Envelope:")
252                 
253                 sub = col.column(align=True)
254                 sub.itemR(bone, "envelope_distance", text="Distance")
255                 sub.itemR(bone, "envelope_weight", text="Weight")
256                 col.itemR(bone, "multiply_vertexgroup_with_envelope", text="Multiply")
257
258                 sub = col.column(align=True)
259                 sub.itemL(text="Radius:")
260                 sub.itemR(bone, "head_radius", text="Head")
261                 sub.itemR(bone, "tail_radius", text="Tail")
262
263                 col = split.column()
264                 col.itemL(text="Curved Bones:")
265                 
266                 sub = col.column(align=True)
267                 sub.itemR(bone, "bbone_segments", text="Segments")
268                 sub.itemR(bone, "bbone_in", text="Ease In")
269                 sub.itemR(bone, "bbone_out", text="Ease Out")
270                 
271                 col.itemL(text="Offset:")
272                 col.itemR(bone, "cyclic_offset")
273
274 bpy.types.register(BONE_PT_context_bone)
275 bpy.types.register(BONE_PT_transform)
276 bpy.types.register(BONE_PT_transform_locks)
277 bpy.types.register(BONE_PT_bone)
278 bpy.types.register(BONE_PT_deform)
279 bpy.types.register(BONE_PT_inverse_kinematics)