reproject operator, use to reproject edited renders back into textures.
[blender.git] / release / scripts / ui / properties_data_bone.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20 import bpy
21 from rna_prop_ui import PropertyPanel
22
23 narrowui = 180
24
25
26 class BoneButtonsPanel(bpy.types.Panel):
27     bl_space_type = 'PROPERTIES'
28     bl_region_type = 'WINDOW'
29     bl_context = "bone"
30
31     def poll(self, context):
32         return (context.bone or context.edit_bone)
33
34
35 class BONE_PT_context_bone(BoneButtonsPanel):
36     bl_label = ""
37     bl_show_header = False
38
39     def draw(self, context):
40         layout = self.layout
41
42         bone = context.bone
43         if not bone:
44             bone = context.edit_bone
45
46         row = layout.row()
47         row.label(text="", icon='BONE_DATA')
48         row.prop(bone, "name", text="")
49
50
51 class BONE_PT_custom_props(BoneButtonsPanel, PropertyPanel):
52
53     @property
54     def _context_path(self):
55         obj = bpy.context.object
56         if obj and obj.mode == 'POSE':
57             return "active_pose_bone"
58         else:
59             return "active_bone"
60
61
62 class BONE_PT_transform(BoneButtonsPanel):
63     bl_label = "Transform"
64
65     def draw(self, context):
66         layout = self.layout
67
68         ob = context.object
69         bone = context.bone
70         wide_ui = context.region.width > narrowui
71
72         if not bone:
73             bone = context.edit_bone
74             if wide_ui:
75                 row = layout.row()
76                 row.column().prop(bone, "head")
77                 row.column().prop(bone, "tail")
78
79                 col = row.column()
80                 sub = col.column(align=True)
81                 sub.label(text="Roll:")
82                 sub.prop(bone, "roll", text="")
83                 sub.label()
84                 sub.prop(bone, "locked")
85             else:
86                 col = layout.column()
87                 col.prop(bone, "head")
88                 col.prop(bone, "tail")
89                 col.prop(bone, "roll")
90                 col.prop(bone, "locked")
91
92         else:
93             pchan = ob.pose.bones[context.bone.name]
94
95             if wide_ui:
96                 row = layout.row()
97                 col = row.column()
98                 col.prop(pchan, "location")
99                 col.active = not (bone.parent and bone.connected)
100
101                 col = row.column()
102                 if pchan.rotation_mode == 'QUATERNION':
103                     col.prop(pchan, "rotation_quaternion", text="Rotation")
104                 elif pchan.rotation_mode == 'AXIS_ANGLE':
105                     #col.label(text="Rotation")
106                     #col.prop(pchan, "rotation_angle", text="Angle")
107                     #col.prop(pchan, "rotation_axis", text="Axis")
108                     col.prop(pchan, "rotation_axis_angle", text="Rotation")
109                 else:
110                     col.prop(pchan, "rotation_euler", text="Rotation")
111
112                 row.column().prop(pchan, "scale")
113
114                 layout.prop(pchan, "rotation_mode")
115             else:
116                 col = layout.column()
117                 sub = col.column()
118                 sub.active = not (bone.parent and bone.connected)
119                 sub.prop(pchan, "location")
120                 col.label(text="Rotation:")
121                 col.prop(pchan, "rotation_mode", text="")
122                 if pchan.rotation_mode == 'QUATERNION':
123                     col.prop(pchan, "rotation_quaternion", text="")
124                 elif pchan.rotation_mode == 'AXIS_ANGLE':
125                     col.prop(pchan, "rotation_axis_angle", text="")
126                 else:
127                     col.prop(pchan, "rotation_euler", text="")
128                 col.prop(pchan, "scale")
129
130
131 class BONE_PT_transform_locks(BoneButtonsPanel):
132     bl_label = "Transform Locks"
133     bl_default_closed = True
134
135     def poll(self, context):
136         return context.bone
137
138     def draw(self, context):
139         layout = self.layout
140
141         ob = context.object
142         bone = context.bone
143         pchan = ob.pose.bones[context.bone.name]
144
145         row = layout.row()
146         col = row.column()
147         col.prop(pchan, "lock_location")
148         col.active = not (bone.parent and bone.connected)
149
150         col = row.column()
151         if pchan.rotation_mode in ('QUATERNION', 'AXIS_ANGLE'):
152             col.prop(pchan, "lock_rotations_4d", text="Lock Rotation")
153             if pchan.lock_rotations_4d:
154                 col.prop(pchan, "lock_rotation_w", text="W")
155             col.prop(pchan, "lock_rotation", text="")
156         else:
157             col.prop(pchan, "lock_rotation", text="Rotation")
158
159         row.column().prop(pchan, "lock_scale")
160
161
162 class BONE_PT_relations(BoneButtonsPanel):
163     bl_label = "Relations"
164
165     def draw(self, context):
166         layout = self.layout
167
168         ob = context.object
169         bone = context.bone
170         arm = context.armature
171         wide_ui = context.region.width > narrowui
172
173         if not bone:
174             bone = context.edit_bone
175             pchan = None
176         else:
177             pchan = ob.pose.bones[context.bone.name]
178
179         split = layout.split()
180
181         col = split.column()
182         col.label(text="Layers:")
183         col.prop(bone, "layer", text="")
184
185         col.separator()
186
187         if ob and pchan:
188             col.label(text="Bone Group:")
189             col.prop_object(pchan, "bone_group", ob.pose, "bone_groups", text="")
190
191         if wide_ui:
192             col = split.column()
193         col.label(text="Parent:")
194         if context.bone:
195             col.prop(bone, "parent", text="")
196         else:
197             col.prop_object(bone, "parent", arm, "edit_bones", text="")
198
199         sub = col.column()
200         sub.active = (bone.parent is not None)
201         sub.prop(bone, "connected")
202         sub.prop(bone, "hinge", text="Inherit Rotation")
203         sub.prop(bone, "inherit_scale", text="Inherit Scale")
204         sub = col.column()
205         sub.active = (not bone.parent or not bone.connected)
206         sub.prop(bone, "local_location", text="Local Location")
207
208
209 class BONE_PT_display(BoneButtonsPanel):
210     bl_label = "Display"
211
212     def poll(self, context):
213         return context.bone
214
215     def draw(self, context):
216         layout = self.layout
217
218         ob = context.object
219         bone = context.bone
220         wide_ui = context.region.width > narrowui
221
222         if not bone:
223             bone = context.edit_bone
224             pchan = None
225         else:
226             pchan = ob.pose.bones[context.bone.name]
227
228         if ob and pchan:
229
230             split = layout.split()
231
232             col = split.column()
233             col.prop(bone, "draw_wire", text="Wireframe")
234             col.prop(bone, "hidden", text="Hide")
235
236             if wide_ui:
237                 col = split.column()
238
239             col.label(text="Custom Shape:")
240             col.prop(pchan, "custom_shape", text="")
241             if pchan.custom_shape:
242                 col.prop_object(pchan, "custom_shape_transform", ob.pose, "bones", text="At")
243
244
245 class BONE_PT_inverse_kinematics(BoneButtonsPanel):
246     bl_label = "Inverse Kinematics"
247     bl_default_closed = True
248
249     def poll(self, context):
250         return context.active_pose_bone
251
252     def draw(self, context):
253         layout = self.layout
254
255         ob = context.object
256         bone = context.bone
257         pchan = ob.pose.bones[bone.name]
258         wide_ui = context.region.width > narrowui
259
260         split = layout.split(percentage=0.25)
261         split.prop(pchan, "ik_dof_x", text="X")
262         split.active = pchan.has_ik
263         row = split.row()
264         row.prop(pchan, "ik_stiffness_x", text="Stiffness", slider=True)
265         row.active = pchan.ik_dof_x and pchan.has_ik
266
267         if wide_ui:
268             split = layout.split(percentage=0.25)
269             sub = split.row()
270         else:
271             sub = layout.column(align=True)
272         sub.prop(pchan, "ik_limit_x", text="Limit")
273         sub.active = pchan.ik_dof_x and pchan.has_ik
274         if wide_ui:
275             sub = split.row(align=True)
276         sub.prop(pchan, "ik_min_x", text="")
277         sub.prop(pchan, "ik_max_x", text="")
278         sub.active = pchan.ik_dof_x and pchan.ik_limit_x and pchan.has_ik
279
280         split = layout.split(percentage=0.25)
281         split.prop(pchan, "ik_dof_y", text="Y")
282         split.active = pchan.has_ik and pchan.has_ik
283         row = split.row()
284         row.prop(pchan, "ik_stiffness_y", text="Stiffness", slider=True)
285         row.active = pchan.ik_dof_y and pchan.has_ik
286
287         if wide_ui:
288             split = layout.split(percentage=0.25)
289             sub = split.row()
290         else:
291             sub = layout.column(align=True)
292         sub.prop(pchan, "ik_limit_y", text="Limit")
293         sub.active = pchan.ik_dof_y and pchan.has_ik
294         if wide_ui:
295             sub = split.row(align=True)
296         sub.prop(pchan, "ik_min_y", text="")
297         sub.prop(pchan, "ik_max_y", text="")
298         sub.active = pchan.ik_dof_y and pchan.ik_limit_y and pchan.has_ik
299
300         split = layout.split(percentage=0.25)
301         split.prop(pchan, "ik_dof_z", text="Z")
302         split.active = pchan.has_ik and pchan.has_ik
303         sub = split.row()
304         sub.prop(pchan, "ik_stiffness_z", text="Stiffness", slider=True)
305         sub.active = pchan.ik_dof_z and pchan.has_ik
306
307         if wide_ui:
308             split = layout.split(percentage=0.25)
309             sub = split.row()
310         else:
311             sub = layout.column(align=True)
312         sub.prop(pchan, "ik_limit_z", text="Limit")
313         sub.active = pchan.ik_dof_z and pchan.has_ik
314         if wide_ui:
315             sub = split.row(align=True)
316         sub.prop(pchan, "ik_min_z", text="")
317         sub.prop(pchan, "ik_max_z", text="")
318         sub.active = pchan.ik_dof_z and pchan.ik_limit_z and pchan.has_ik
319         split = layout.split()
320         split.prop(pchan, "ik_stretch", text="Stretch", slider=True)
321         if wide_ui:
322             split.label()
323         split.active = pchan.has_ik
324
325         if ob.pose.ik_solver == 'ITASC':
326             split = layout.split()
327             col = split.column()
328             col.prop(pchan, "ik_rot_control", text="Control Rotation")
329             col.active = pchan.has_ik
330             if wide_ui:
331                 col = split.column()
332             col.prop(pchan, "ik_rot_weight", text="Weight", slider=True)
333             col.active = pchan.has_ik
334             # not supported yet
335             #row = layout.row()
336             #row.prop(pchan, "ik_lin_control", text="Joint Size")
337             #row.prop(pchan, "ik_lin_weight", text="Weight", slider=True)
338
339
340 class BONE_PT_deform(BoneButtonsPanel):
341     bl_label = "Deform"
342     bl_default_closed = True
343
344     def draw_header(self, context):
345         bone = context.bone
346
347         if not bone:
348             bone = context.edit_bone
349
350         self.layout.prop(bone, "deform", text="")
351
352     def draw(self, context):
353         layout = self.layout
354
355         bone = context.bone
356         wide_ui = context.region.width > narrowui
357
358         if not bone:
359             bone = context.edit_bone
360
361         layout.active = bone.deform
362
363         split = layout.split()
364
365         col = split.column()
366         col.label(text="Envelope:")
367
368         sub = col.column(align=True)
369         sub.prop(bone, "envelope_distance", text="Distance")
370         sub.prop(bone, "envelope_weight", text="Weight")
371         col.prop(bone, "multiply_vertexgroup_with_envelope", text="Multiply")
372
373         sub = col.column(align=True)
374         sub.label(text="Radius:")
375         sub.prop(bone, "head_radius", text="Head")
376         sub.prop(bone, "tail_radius", text="Tail")
377
378         if wide_ui:
379             col = split.column()
380         col.label(text="Curved Bones:")
381
382         sub = col.column(align=True)
383         sub.prop(bone, "bbone_segments", text="Segments")
384         sub.prop(bone, "bbone_in", text="Ease In")
385         sub.prop(bone, "bbone_out", text="Ease Out")
386
387         col.label(text="Offset:")
388         col.prop(bone, "cyclic_offset")
389
390 classes = [
391     BONE_PT_context_bone,
392     BONE_PT_transform,
393     BONE_PT_transform_locks,
394     BONE_PT_relations,
395     BONE_PT_display,
396     BONE_PT_inverse_kinematics,
397     BONE_PT_deform,
398
399     BONE_PT_custom_props]
400
401
402 def register():
403     register = bpy.types.register
404     for cls in classes:
405         register(cls)
406
407
408 def unregister():
409     unregister = bpy.types.unregister
410     for cls in classes:
411         unregister(cls)
412
413 if __name__ == "__main__":
414     register()